You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2022/07/28 07:23:41 UTC

[incubator-nuttx] branch master updated (f1fdba28a7 -> 82ad4b0e08)

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

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


    from f1fdba28a7 include: Add IPTR/IOBJ definitions.
     new 9db6aaa5c7 stm32wb: fixing IPCC 'putreg' calls
     new 82ad4b0e08 stm32wb: adding BLE support

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


Summary of changes:
 arch/arm/src/stm32wb/Kconfig                       | 232 ++++++
 arch/arm/src/stm32wb/Make.defs                     |  16 +-
 arch/arm/src/stm32wb/hardware/stm32wb_ipcc.h       |   2 +-
 arch/arm/src/stm32wb/stm32wb_blehci.c              | 348 +++++++++
 .../src/stm32wb/stm32wb_blehci.h}                  |  25 +-
 arch/arm/src/stm32wb/stm32wb_ipcc.c                |  18 +-
 arch/arm/src/stm32wb/stm32wb_ipcc.h                | 104 +++
 arch/arm/src/stm32wb/stm32wb_mbox.c                | 813 +++++++++++++++++++++
 arch/arm/src/stm32wb/stm32wb_mbox.h                | 174 +++++
 .../sam_eefc.h => stm32wb/stm32wb_mbox_list.h}     | 126 ++--
 arch/arm/src/stm32wb/stm32wb_mbox_shci.h           | 186 +++++
 arch/arm/src/stm32wb/stm32wb_rcc.c                 |  11 +
 boards/arm/stm32wb/nucleo-wb55rg/README.txt        |   7 +
 .../nucleo-wb55rg/configs/{nsh => ble}/defconfig   |  14 +
 .../stm32wb/nucleo-wb55rg/include/nucleo-wb55rg.h  |   6 +
 .../arm/stm32wb/nucleo-wb55rg/src/stm32_appinit.c  |  26 +
 16 files changed, 2025 insertions(+), 83 deletions(-)
 create mode 100644 arch/arm/src/stm32wb/stm32wb_blehci.c
 copy arch/{risc-v/src/bl602/bl602_efuse.h => arm/src/stm32wb/stm32wb_blehci.h} (79%)
 create mode 100644 arch/arm/src/stm32wb/stm32wb_mbox.c
 create mode 100644 arch/arm/src/stm32wb/stm32wb_mbox.h
 copy arch/arm/src/{samv7/sam_eefc.h => stm32wb/stm32wb_mbox_list.h} (51%)
 create mode 100644 arch/arm/src/stm32wb/stm32wb_mbox_shci.h
 copy boards/arm/stm32wb/nucleo-wb55rg/configs/{nsh => ble}/defconfig (77%)


[incubator-nuttx] 01/02: stm32wb: fixing IPCC 'putreg' calls

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

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

commit 9db6aaa5c7460cbc1c3efe614733af86b7e6cc6c
Author: Sergey Nikitenko <s....@me.com>
AuthorDate: Sun Jul 3 23:08:06 2022 +0300

    stm32wb: fixing IPCC 'putreg' calls
---
 arch/arm/src/stm32wb/stm32wb_ipcc.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/arch/arm/src/stm32wb/stm32wb_ipcc.c b/arch/arm/src/stm32wb/stm32wb_ipcc.c
index 1569b75be3..9d211acf0c 100644
--- a/arch/arm/src/stm32wb/stm32wb_ipcc.c
+++ b/arch/arm/src/stm32wb/stm32wb_ipcc.c
@@ -51,27 +51,27 @@ void stm32wb_ipccreset(void)
 
   /* Disable CPU1 IPCC interrupts */
 
-  putreg32(STM32WB_IPCC_C1CR, 0x00000000);
+  putreg32(0x00000000, STM32WB_IPCC_C1CR);
 
   /* Clear CPU1 IPCC receive channel status */
 
-  putreg32(STM32WB_IPCC_C1SCR, IPCC_C1SCR_CLR_MASK);
+  putreg32(IPCC_C1SCR_CLR_MASK, STM32WB_IPCC_C1SCR);
 
   /* Clear CPU2 IPCC receive channel status */
 
-  putreg32(STM32WB_IPCC_C2SCR, IPCC_C2SCR_CLR_MASK);
+  putreg32(IPCC_C2SCR_CLR_MASK, STM32WB_IPCC_C2SCR);
 
   /* Disable CPU1 transmit/receive channels */
 
   regval = getreg32(STM32WB_IPCC_C1MR);
   regval |= IPCC_C1MR_OM_MASK | IPCC_C1MR_FM_MASK;
-  putreg32(STM32WB_IPCC_C1MR, regval);
+  putreg32(regval, STM32WB_IPCC_C1MR);
 
   /* Disable CPU2 transmit/receive channels */
 
   regval = getreg32(STM32WB_IPCC_C2MR);
   regval |= IPCC_C2MR_OM_MASK | IPCC_C2MR_FM_MASK;
-  putreg32(STM32WB_IPCC_C2MR, regval);
+  putreg32(regval, STM32WB_IPCC_C2MR);
 }
 
 /****************************************************************************
@@ -90,19 +90,19 @@ void stm32wb_ipccenable(void)
 
   regval = getreg32(STM32WB_RCC_C2AHB3ENR);
   regval |= RCC_C2AHB3ENR_IPCCEN;
-  putreg32(STM32WB_RCC_C2AHB3ENR, regval);
+  putreg32(regval, STM32WB_RCC_C2AHB3ENR);
 
   /* Enable EXTI event request for C1SEV interrupt to CPU2 */
 
   regval = getreg32(STM32WB_EXTI_C2EMR2);
   regval |= EXTI_C2EMR2_EM(EXTI_EVT_C1SEV);
-  putreg32(STM32WB_EXTI_C2EMR2, regval);
+  putreg32(regval, STM32WB_EXTI_C2EMR2);
 
   /* Enable EXTI rising edge trigger for C1SEV interrupt to CPU2 */
 
   regval = getreg32(STM32WB_EXTI_RTSR2);
   regval |= EXTI_RTSR2_RT(EXTI_EVT_C1SEV);
-  putreg32(STM32WB_EXTI_RTSR2, regval);
+  putreg32(regval, STM32WB_EXTI_RTSR2);
 
   /* Set the internal event flag and send an event to CPU2 */
 
@@ -116,5 +116,5 @@ void stm32wb_ipccenable(void)
 
   regval = getreg32(STM32WB_PWR_CR4);
   regval |= PWR_CR4_C2BOOT;
-  putreg32(STM32WB_PWR_CR4, regval);
+  putreg32(regval, STM32WB_PWR_CR4);
 }


[incubator-nuttx] 02/02: stm32wb: adding BLE support

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

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

commit 82ad4b0e080a4ba3e17506c6504114540c78db8e
Author: Sergey Nikitenko <s....@me.com>
AuthorDate: Wed Jul 27 16:19:20 2022 +0300

    stm32wb: adding BLE support
---
 arch/arm/src/stm32wb/Kconfig                       | 232 ++++++
 arch/arm/src/stm32wb/Make.defs                     |  16 +-
 arch/arm/src/stm32wb/hardware/stm32wb_ipcc.h       |   2 +-
 arch/arm/src/stm32wb/stm32wb_blehci.c              | 348 +++++++++
 .../stm32wb/{stm32wb_ipcc.h => stm32wb_blehci.h}   |  34 +-
 arch/arm/src/stm32wb/stm32wb_ipcc.h                | 104 +++
 arch/arm/src/stm32wb/stm32wb_mbox.c                | 813 +++++++++++++++++++++
 arch/arm/src/stm32wb/stm32wb_mbox.h                | 174 +++++
 arch/arm/src/stm32wb/stm32wb_mbox_list.h           | 144 ++++
 arch/arm/src/stm32wb/stm32wb_mbox_shci.h           | 186 +++++
 arch/arm/src/stm32wb/stm32wb_rcc.c                 |  11 +
 boards/arm/stm32wb/nucleo-wb55rg/README.txt        |   7 +
 .../stm32wb/nucleo-wb55rg/configs/ble/defconfig    |  55 ++
 .../stm32wb/nucleo-wb55rg/include/nucleo-wb55rg.h  |   6 +
 .../arm/stm32wb/nucleo-wb55rg/src/stm32_appinit.c  |  26 +
 15 files changed, 2130 insertions(+), 28 deletions(-)

diff --git a/arch/arm/src/stm32wb/Kconfig b/arch/arm/src/stm32wb/Kconfig
index 9396f76881..d13bcc0b03 100644
--- a/arch/arm/src/stm32wb/Kconfig
+++ b/arch/arm/src/stm32wb/Kconfig
@@ -941,4 +941,236 @@ config STM32WB_SPI_DMA
 
 endmenu
 
+config STM32WB_MBOX
+	bool
+	default n
+	select STM32WB_IPCC
+
+menuconfig STM32WB_BLE
+	bool "BLE"
+	default n
+	select STM32WB_MBOX
+	---help---
+		Enable BLE support.
+
+if STM32WB_BLE
+
+config STM32WB_BLE_C2HOST
+	bool "Enable CPU2 HOST stack"
+	default y
+
+config STM32WB_BLE_MAX_CONN
+	int "Maximum BLE simultaneous connections"
+	range 1 8
+	default 2
+
+config STM32WB_BLE_GATT_MAX_ATTR_NUM
+	int "GATT attributes max count"
+	range 9 255
+	default 64
+
+config STM32WB_BLE_GATT_MAX_SVC_NUM
+	int "GATT services max count"
+	range 2 64
+	default 8
+
+config STM32WB_BLE_GATT_ATTR_BUF_SIZE
+	int "GATT attributes storage buf size"
+	default 1344
+	---help---
+		Size of the storage area for attribute values. Hardcoded in CPU2 firmware.
+
+config STM32WB_BLE_DLE
+	bool "Support Data Length Extension (DLE)"
+	default y
+
+config STM32WB_BLE_MAX_ATT_MTU
+	int "Maximum supported attribute MTU"
+	range 23 512
+	default 156
+
+config STM32WB_BLE_SLAVE_SCA
+	int "Sleep clock accuracy in slave mode [PPM]"
+	default 500
+	---help---
+		Sleep clock accuracy (ppm value) in slave mode.
+
+choice 
+	prompt "Sleep clock accuracy in master mode"
+	default STM32WB_BLE_MASTER_SCA_0
+	---help---
+		Sleep clock accuracy in master mode.
+
+config STM32WB_BLE_MASTER_SCA_0
+	bool "251-500 ppm"
+
+config STM32WB_BLE_MASTER_SCA_1
+	bool "151-250 ppm"
+
+config STM32WB_BLE_MASTER_SCA_2
+	bool "101-150 ppm"
+
+config STM32WB_BLE_MASTER_SCA_3
+	bool "76-100 ppm"
+
+config STM32WB_BLE_MASTER_SCA_4
+	bool "51-75 ppm"
+
+config STM32WB_BLE_MASTER_SCA_5
+	bool "31-50 ppm"
+
+config STM32WB_BLE_MASTER_SCA_6
+	bool "21-30 ppm"
+
+config STM32WB_BLE_MASTER_SCA_7
+	bool "0-20 ppm"
+
+endchoice # Sleep clock accuracy in master mode
+
+config STM32WB_BLE_MASTER_SCA
+	int
+	default 7 if STM32WB_BLE_MASTER_SCA_7
+	default 6 if STM32WB_BLE_MASTER_SCA_6
+	default 5 if STM32WB_BLE_MASTER_SCA_5
+	default 4 if STM32WB_BLE_MASTER_SCA_4
+	default 3 if STM32WB_BLE_MASTER_SCA_3
+	default 2 if STM32WB_BLE_MASTER_SCA_2
+	default 1 if STM32WB_BLE_MASTER_SCA_1
+	default 0
+
+choice 
+	prompt "Low speed clock source"
+	default STM32WB_BLE_LS_CLK_SRC_LSE
+	---help---
+		Low speed 32 kHz clock source.
+
+config STM32WB_BLE_LS_CLK_SRC_LSE
+	bool "LSE"
+
+config STM32WB_BLE_LS_CLK_SRC_HSE
+	bool "HSE"
+
+endchoice # Low speed clock source
+
+config STM32WB_BLE_LS_CLK_SRC
+	int
+	default 1 if STM32WB_BLE_LS_CLKSRC_HSE
+	default 0
+
+config STM32WB_BLE_MAX_CONN_EVT_LENGTH
+	hex "Max connection event length"
+	default 0xffffffff
+	---help---
+		Maximum duration of a slave connection event in units of 625/256us (~2.44us).
+
+config STM32WB_BLE_HSE_STARTUP
+	hex "HSE startup time"
+	default 0x148
+	---help---
+		HSE startup time in units of 625/256us (~2.44us).
+
+config STM32WB_BLE_VITERBI
+	bool "Enable Viterbi algorithm"
+	default y
+	---help---
+		Enable Viterbi algorithm implementation
+
+config STM32WB_BLE_MAX_INITOR_COC_NUM
+	int "Max number of connection-oriented channels"
+	range 0 64
+	default 32
+	---help---
+		Maximum number of connection-oriented channels in initiator mode.
+
+config STM32WB_BLE_SVC_CHANGED_CHAR
+	bool "Enable service changed characteristic"
+	default n
+
+config STM32WB_BLE_WRITABLE_DEVICE_NAME
+	bool "Writable device name"
+	default y
+
+config STM32WB_BLE_CHAN_SEL_ALG2
+	bool "Enable channel selection algorithm 2"
+	default n
+
+choice 
+	prompt "Power class"
+	default STM32WB_BLE_POWER_CLASS_2_3
+
+config STM32WB_BLE_POWER_CLASS_2_3
+	bool "Power Class 2-3"
+
+config STM32WB_BLE_POWER_CLASS_1
+	bool "Power Class 1"
+
+endchoice # Power class
+
+config STM32WB_BLE_MIN_TX_POWER
+	int "Minimum transmit power [dBm]"
+	range -127 20
+	default 0
+
+config STM32WB_BLE_MAX_TX_POWER
+	int "Maximum transmit power [dBm]"
+	range -127 20
+	default 0
+
+choice 
+	prompt "AGC RSSI model"
+	default STM32WB_BLE_AGC_RSSI_LEGACY
+
+config STM32WB_BLE_AGC_RSSI_LEGACY
+	bool "AGC RSSI Legacy"
+
+config STM32WB_BLE_AGC_RSSI_IMPROVED
+	bool "AGC RSSI Improved"
+
+endchoice # AGC RSSI model
+
+config STM32WB_BLE_ADVERTISING
+	bool "Support advertising"
+	default y
+
+config STM32WB_BLE_SCANNING
+	bool "Support scanning"
+	default y
+
+config STM32WB_BLE_LE_2M_PHY
+	bool "Support LE 2M PHY"
+	default y
+
+config STM32WB_BLE_LE_CODED_PHY
+	bool "Support LE Coded PHY"
+	default y if STM32WB_STM32WB15 || STM32WB_STM32WB35 || STM32WB_STM32WB55
+	default n
+	depends on STM32WB_STM32WB15 || STM32WB_STM32WB35 || STM32WB_STM32WB55
+
+config STM32WB_BLE_TTY_NAME
+	string "BLE TTY device name"
+	default "/dev/ttyHCI0"
+	depends on UART_BTH4
+
+config STM32WB_BLE_FICR_STATIC_ADDR
+	bool "Configure factory generated static random address"
+	default n
+
+config STM32WB_BLE_PUB_ADDR
+	hex "Configure BT public address"
+	default 0x0000000000
+
+endif # STM32WB_BLE
+
+if STM32WB_MBOX
+
+config STM32WB_MBOX_TX_CMD_QUEUE_LEN
+	int "Mailbox TX command queue length"
+	default 2
+
+config STM32WB_MBOX_RX_EVT_QUEUE_LEN
+	int "Mailbox RX event queue length"
+	default 5
+
+endif # STM32WB_MBOX
+
 endif # ARCH_CHIP_STM32WB
diff --git a/arch/arm/src/stm32wb/Make.defs b/arch/arm/src/stm32wb/Make.defs
index a0c9611422..886776d368 100644
--- a/arch/arm/src/stm32wb/Make.defs
+++ b/arch/arm/src/stm32wb/Make.defs
@@ -81,10 +81,6 @@ ifeq ($(CONFIG_STM32WB_PWR),y)
 CHIP_CSRCS += stm32wb_exti_pwr.c
 endif
 
-ifeq ($(CONFIG_STM32WB_IPCC),y)
-CHIP_CSRCS += stm32wb_ipcc.c
-endif
-
 ifeq ($(CONFIG_STM32WB_RTC),y)
 ifeq ($(CONFIG_RTC_ALARM),y)
 CHIP_CSRCS += stm32wb_exti_alarm.c
@@ -97,6 +93,18 @@ CHIP_CSRCS += stm32wb_rtc.c stm32wb_rtc_lowerhalf.c
 endif
 endif
 
+ifeq ($(CONFIG_STM32WB_IPCC),y)
+CHIP_CSRCS += stm32wb_ipcc.c
+endif
+
+ifeq ($(CONFIG_STM32WB_MBOX),y)
+CHIP_CSRCS += stm32wb_mbox.c
+endif
+
+ifeq ($(CONFIG_STM32WB_BLE),y)
+CHIP_CSRCS += stm32wb_blehci.c
+endif
+
 ifeq ($(CONFIG_DEBUG_FEATURES),y)
 CHIP_CSRCS += stm32wb_dumpgpio.c
 endif
diff --git a/arch/arm/src/stm32wb/hardware/stm32wb_ipcc.h b/arch/arm/src/stm32wb/hardware/stm32wb_ipcc.h
index 740f408849..178ccd90a6 100644
--- a/arch/arm/src/stm32wb/hardware/stm32wb_ipcc.h
+++ b/arch/arm/src/stm32wb/hardware/stm32wb_ipcc.h
@@ -34,7 +34,7 @@
 #define STM32WB_IPCC_C2CR_OFFSET      0x0010  /* CPU2 control register */
 #define STM32WB_IPCC_C2MR_OFFSET      0x0014  /* CPU2 mask register */
 #define STM32WB_IPCC_C2SCR_OFFSET     0x0018  /* CPU2 status set/clear register */
-#define STM32WB_IPCC_C2TOC1SR_OFFSET  0x001c  /* CPU2 to CPU2 status register */
+#define STM32WB_IPCC_C2TOC1SR_OFFSET  0x001c  /* CPU2 to CPU1 status register */
 
 /* Register Addresses *******************************************************/
 
diff --git a/arch/arm/src/stm32wb/stm32wb_blehci.c b/arch/arm/src/stm32wb/stm32wb_blehci.c
new file mode 100644
index 0000000000..560a03dc1e
--- /dev/null
+++ b/arch/arm/src/stm32wb/stm32wb_blehci.c
@@ -0,0 +1,348 @@
+/****************************************************************************
+ * arch/arm/src/stm32wb/stm32wb_blehci.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 <assert.h>
+#include <debug.h>
+
+#include <nuttx/wireless/bluetooth/bt_hci.h>
+#include <nuttx/wireless/bluetooth/bt_driver.h>
+#include <nuttx/arch.h>
+#include <nuttx/wqueue.h>
+
+#if defined(CONFIG_UART_BTH4)
+#  include <nuttx/serial/uart_bth4.h>
+#endif
+
+#include "stm32wb_ipcc.h"
+#include "stm32wb_mbox.h"
+#include "stm32wb_mbox_shci.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define STM32WB_BLE_PREP_WRITE_NUM \
+  STM32WB_MBOX_DEFAULT_BLE_PREP_WRITE_NUM(CONFIG_STM32WB_BLE_MAX_ATT_MTU)
+
+#define STM32WB_C2_MEM_BLOCK_NUM \
+  STM32WB_MBOX_DEFAULT_C2_MEM_BLOCK_NUM(CONFIG_STM32WB_BLE_MAX_ATT_MTU, \
+                                        CONFIG_STM32WB_BLE_MAX_CONN, \
+                                        STM32WB_BLE_PREP_WRITE_NUM)
+
+#ifdef CONFIG_STM32WB_BLE_C2HOST
+#  define STM32WB_BLE_C2HOST              STM32WB_SHCI_BLE_INIT_OPT_STACK_LL_HOST
+#else
+#  define STM32WB_BLE_C2HOST              STM32WB_SHCI_BLE_INIT_OPT_STACK_LL
+#endif
+
+#ifdef CONFIG_STM32WB_BLE_SVC_CHANGED_CHAR
+#  define STM32WB_BLE_SVC_CHANGED_CHAR    STM32WB_SHCI_BLE_INIT_OPT_SVC_CHCHAR_ENABLED
+#else
+#  define STM32WB_BLE_SVC_CHANGED_CHAR    STM32WB_SHCI_BLE_INIT_OPT_SVC_CHCHAR_DISABLED
+#endif
+
+#ifdef CONFIG_STM32WB_BLE_WRITABLE_DEVICE_NAME
+#  define STM32WB_BLE_DEVICE_NAME_MODE    STM32WB_SHCI_BLE_INIT_OPT_DEVICE_NAME_MODE_RW
+#else
+#  define STM32WB_BLE_DEVICE_NAME_MODE    STM32WB_SHCI_BLE_INIT_OPT_DEVICE_NAME_MODE_RO
+#endif
+
+#ifdef CONFIG_STM32WB_BLE_CHAN_SEL_ALG2
+#  define STM32WB_BLE_CS_ALG2             STM32WB_SHCI_BLE_INIT_OPT_CS_ALG2_ENABLED
+#else
+#  define STM32WB_BLE_CS_ALG2             STM32WB_SHCI_BLE_INIT_OPT_CS_ALG2_DISABLED
+#endif
+
+#ifdef CONFIG_STM32WB_BLE_POWER_CLASS_1
+#  define STM32WB_BLE_POWER_CLASS         STM32WB_SHCI_BLE_INIT_OPT_POWER_CLASS_1
+#else
+#  define STM32WB_BLE_POWER_CLASS         STM32WB_SHCI_BLE_INIT_OPT_POWER_CLASS_2_3
+#endif
+
+#define STM32WB_BLE_INIT_OPTIONS \
+  (STM32WB_BLE_C2HOST | STM32WB_BLE_SVC_CHANGED_CHAR | \
+   STM32WB_BLE_DEVICE_NAME_MODE | STM32WB_BLE_CS_ALG2 | \
+   STM32WB_BLE_POWER_CLASS)
+
+#ifdef CONFIG_STM32WB_BLE_AGC_RSSI_IMPROVED
+#  define STM32WB_BLE_RXMOD_AGC_RSSI      STM32WB_SHCI_BLE_INIT_RXMOD_AGC_RSSI_IMPROVED
+#else
+#  define STM32WB_BLE_RXMOD_AGC_RSSI      STM32WB_SHCI_BLE_INIT_RXMOD_AGC_RSSI_LEGACY
+#endif
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int stm32wb_blehci_driveropen(struct bt_driver_s *btdev);
+static int stm32wb_blehci_driversend(struct bt_driver_s *btdev,
+                                     enum bt_buf_type_e type,
+                                     void *data, size_t len);
+static int stm32wb_blehci_rxevt(struct stm32wb_mbox_evt_s *evt);
+static void stm32wb_blehci_bleinit(void);
+static int stm32wb_blehci_driverinitialize(void);
+static void stm32wb_blehci_drvinitworker(void *arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct bt_driver_s g_blehci_driver =
+{
+  .head_reserve = 0,
+  .open         = stm32wb_blehci_driveropen,
+  .send         = stm32wb_blehci_driversend
+};
+
+static sem_t  g_excl_sem = SEM_INITIALIZER(1);
+struct work_s g_drv_init_work;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32wb_blehci_driveropen
+ ****************************************************************************/
+
+static int stm32wb_blehci_driveropen(struct bt_driver_s *btdev)
+{
+  return 0;
+}
+
+/****************************************************************************
+ * Name: stm32wb_blehci_driversend
+ ****************************************************************************/
+
+static int stm32wb_blehci_driversend(struct bt_driver_s *btdev,
+                                     enum bt_buf_type_e type,
+                                     void *data, size_t len)
+{
+  int ret = -EIO;
+
+  if (type == BT_CMD || type == BT_ACL_OUT)
+    {
+      wlinfo("passing type %s to mailbox driver\n",
+             (type == BT_CMD) ? "CMD" : "ACL");
+
+      /* Ensure non-concurrent access */
+
+      ret = nxsem_wait_uninterruptible(&g_excl_sem);
+      if (ret < 0)
+        {
+          return ret;
+        }
+
+      if (type == BT_CMD)
+        {
+          ret = stm32wb_mbox_blecmd(data, len);
+        }
+      else
+        {
+          ret = stm32wb_mbox_bleacl(data, len);
+        }
+
+      nxsem_post(&g_excl_sem);
+    }
+
+  return ret < 0 ? ret : (int)len;
+}
+
+/****************************************************************************
+ * Name: stm32wb_blehci_rxevt
+ ****************************************************************************/
+
+static int stm32wb_blehci_rxevt(struct stm32wb_mbox_evt_s *evt)
+{
+  size_t len;
+
+  switch (evt->type)
+    {
+      case STM32WB_MBOX_HCIEVT:
+        len = sizeof(evt->evt_hdr) + evt->evt_hdr.len;
+        if (evt->evt_hdr.evt == BT_HCI_EVT_CMD_COMPLETE)
+          {
+            wlinfo("received CMD_COMPLETE from mailbox "
+                   "(opcode: 0x%x, status: 0x%x)\n",
+                   *(uint16_t *)((uint8_t *)&evt->evt_hdr + 3),
+                   *((uint8_t *)&evt->evt_hdr + 5));
+          }
+        else
+          {
+            wlinfo("received HCI EVT from mailbox "
+                   "(evt: %d, len: %zu)\n", evt->evt_hdr.evt, len);
+          }
+
+        bt_netdev_receive(&g_blehci_driver, BT_EVT, &evt->evt_hdr, len);
+        break;
+
+      case STM32WB_MBOX_HCIACL:
+        wlinfo("received HCI ACL from mailbox (handle: %d)\n",
+               evt->acl_hdr.handle);
+        len = sizeof(evt->acl_hdr) + evt->acl_hdr.len;
+
+        bt_netdev_receive(&g_blehci_driver, BT_ACL_IN, &evt->acl_hdr, len);
+        break;
+
+      case STM32WB_MBOX_SYSEVT:
+        wlinfo("received SYS event from mailbox (evt: %d)\n",
+               evt->evt_hdr.evt);
+        if (evt->evt_hdr.evt == STM32WB_SHCI_ASYNC_EVT &&
+            *(uint16_t *)(&evt->evt_hdr + 1) == STM32WB_SHCI_ASYNC_EVT_C2RDY)
+          {
+            stm32wb_blehci_bleinit();
+          }
+        break;
+
+      case STM32WB_MBOX_SYSACK:
+
+        /* CPU2 Ready is the only expected response */
+
+        DEBUGASSERT(evt->evt_hdr.evt == STM32WB_SHCI_ACK_EVT_C2RDY);
+
+        if (evt->evt_hdr.evt == STM32WB_SHCI_ACK_EVT_C2RDY)
+          {
+            wlinfo("system command ACK response");
+
+            /* Make driver initialisation in low priority work queue */
+
+            work_queue(LPWORK, &g_drv_init_work,
+                       stm32wb_blehci_drvinitworker, NULL, 0);
+          }
+        break;
+
+      default:
+        break;
+    }
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: stm32wb_blehci_bleinit
+ ****************************************************************************/
+
+static void stm32wb_blehci_bleinit(void)
+{
+  /* Prepare BLE configuration */
+
+  struct stm32wb_shci_ble_init_cfg_s params =
+  {
+    .ble_buf =              NULL,
+    .ble_buf_size =         0,
+    .gatt_attr_num =        CONFIG_STM32WB_BLE_GATT_MAX_ATTR_NUM,
+    .gatt_srv_num =         CONFIG_STM32WB_BLE_GATT_MAX_SVC_NUM,
+    .gatt_attr_buf_size =   CONFIG_STM32WB_BLE_GATT_ATTR_BUF_SIZE,
+    .max_conn =             CONFIG_STM32WB_BLE_MAX_CONN,
+    .dle_enable =           CONFIG_STM32WB_BLE_DLE,
+    .prep_write_op_num =    STM32WB_BLE_PREP_WRITE_NUM,
+    .mem_block_num =        STM32WB_C2_MEM_BLOCK_NUM,
+    .att_max_mtu_size =     CONFIG_STM32WB_BLE_MAX_ATT_MTU,
+    .slave_sca =            CONFIG_STM32WB_BLE_SLAVE_SCA,
+    .master_sca_range =     CONFIG_STM32WB_BLE_MASTER_SCA,
+    .ls_clock_source =      CONFIG_STM32WB_BLE_LS_CLK_SRC,
+    .conn_event_length =    CONFIG_STM32WB_BLE_MAX_CONN_EVT_LENGTH,
+    .hse_startup =          CONFIG_STM32WB_BLE_HSE_STARTUP,
+    .viterbi_enable =       CONFIG_STM32WB_BLE_VITERBI,
+    .options =              STM32WB_BLE_INIT_OPTIONS,
+    .hw_version =           0,
+    .max_initor_coc_num =   CONFIG_STM32WB_BLE_MAX_INITOR_COC_NUM,
+    .tx_power_min =         CONFIG_STM32WB_BLE_MIN_TX_POWER,
+    .tx_power_max =         CONFIG_STM32WB_BLE_MAX_TX_POWER,
+    .rx_model_config =      STM32WB_BLE_RXMOD_AGC_RSSI
+  };
+
+  /* Initialise BLE */
+
+  stm32wb_mbox_bleinit(&params);
+}
+
+/****************************************************************************
+ * Name: stm32wb_blehci_driverinitialize
+ ****************************************************************************/
+
+static int stm32wb_blehci_driverinitialize(void)
+{
+  int ret = 0;
+
+#ifdef CONFIG_UART_BTH4
+  /* Register UART BT H4 device */
+
+  ret = uart_bth4_register(CONFIG_STM32WB_BLE_TTY_NAME, &g_blehci_driver);
+  if (ret < 0)
+    {
+      wlerr("bt_bth4_register error: %d\n", ret);
+      return ret;
+    }
+#elif defined(CONFIG_NET_BLUETOOTH)
+  /* Register network device */
+
+  ret = bt_netdev_register(&g_blehci_driver);
+  if (ret < 0)
+    {
+      wlerr("bt_netdev_register error: %d\n", ret);
+      return ret;
+    }
+#endif
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: stm32wb_blehci_drvinitworker
+ ****************************************************************************/
+
+static void stm32wb_blehci_drvinitworker(void *arg)
+{
+  stm32wb_blehci_driverinitialize();
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32wb_blehci_initialize
+ *
+ * Description:
+ *   Initialize and register BLE HCI driver which interfaces a BLE host
+ *   stack to a BLE controller running on CPU2 via HCI protocol.  Driver
+ *   registration occurs later when CPU2 notifies its ready status.
+ *
+ ****************************************************************************/
+
+void stm32wb_blehci_initialize(void)
+{
+  /* Initialize mbox internal data structures and set
+   * event receive handler.
+   */
+
+  stm32wb_mboxinitialize(stm32wb_blehci_rxevt);
+
+  /* Enable communication hardware and bootup CPU2 */
+
+  stm32wb_mboxenable();
+}
diff --git a/arch/arm/src/stm32wb/stm32wb_ipcc.h b/arch/arm/src/stm32wb/stm32wb_blehci.h
similarity index 74%
copy from arch/arm/src/stm32wb/stm32wb_ipcc.h
copy to arch/arm/src/stm32wb/stm32wb_blehci.h
index 5183c77d7b..84a679ab80 100644
--- a/arch/arm/src/stm32wb/stm32wb_ipcc.h
+++ b/arch/arm/src/stm32wb/stm32wb_blehci.h
@@ -1,5 +1,5 @@
 /****************************************************************************
- * arch/arm/src/stm32wb/stm32wb_ipcc.h
+ * arch/arm/src/stm32wb/stm32wb_blehci.h
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -18,22 +18,18 @@
  *
  ****************************************************************************/
 
-#ifndef __ARCH_ARM_SRC_STM32WB_STM32WB_IPCC_H
-#define __ARCH_ARM_SRC_STM32WB_STM32WB_IPCC_H
+#ifndef __ARCH_ARM_SRC_STM32WB_STM32WB_BLEHCI_H
+#define __ARCH_ARM_SRC_STM32WB_STM32WB_BLEHCI_H
 
 /****************************************************************************
  * Included Files
  ****************************************************************************/
 
 #include <nuttx/config.h>
-
-#include <stdbool.h>
-
-#include "chip.h"
-#include "hardware/stm32wb_ipcc.h"
+#include <sys/types.h>
 
 /****************************************************************************
- * Pre-processor Definitions
+ * Public Data
  ****************************************************************************/
 
 #ifndef __ASSEMBLY__
@@ -52,24 +48,16 @@ extern "C"
  ****************************************************************************/
 
 /****************************************************************************
- * Name: stm32wb_ipccreset
- *
- * Description:
- *   Reset the IPCC registers to default state
- *
- ****************************************************************************/
-
-void stm32wb_ipccreset(void);
-
-/****************************************************************************
- * Name: stm32wb_ipccenable
+ * Name: stm32wb_blehci_initialize
  *
  * Description:
- *   Enable the IPCC and start CPU2
+ *   Initialize and register BLE HCI driver which interfaces a BLE host
+ *   stack to a BLE controller running on CPU2 via HCI protocol.  Driver
+ *   registration occurs later when CPU2 notifies its ready status.
  *
  ****************************************************************************/
 
-void stm32wb_ipccenable(void);
+void stm32wb_blehci_initialize(void);
 
 #undef EXTERN
 #if defined(__cplusplus)
@@ -77,4 +65,4 @@ void stm32wb_ipccenable(void);
 #endif
 
 #endif /* __ASSEMBLY__ */
-#endif /* __ARCH_ARM_SRC_STM32WB_STM32WB_IPCC_H */
+#endif /* __ARCH_ARM_SRC_STM32WB_STM32WB_BLEHCI_H */
diff --git a/arch/arm/src/stm32wb/stm32wb_ipcc.h b/arch/arm/src/stm32wb/stm32wb_ipcc.h
index 5183c77d7b..8f92e3f5e9 100644
--- a/arch/arm/src/stm32wb/stm32wb_ipcc.h
+++ b/arch/arm/src/stm32wb/stm32wb_ipcc.h
@@ -30,6 +30,7 @@
 #include <stdbool.h>
 
 #include "chip.h"
+#include "arm_internal.h"
 #include "hardware/stm32wb_ipcc.h"
 
 /****************************************************************************
@@ -71,6 +72,109 @@ void stm32wb_ipccreset(void);
 
 void stm32wb_ipccenable(void);
 
+/****************************************************************************
+ * Inline Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32wb_ipcc_rxactive
+ *
+ * Description:
+ *   Check channel receive active flag.
+ *
+ ****************************************************************************/
+
+static inline bool stm32wb_ipcc_rxactive(uint8_t chan)
+{
+  return (getreg32(STM32WB_IPCC_C2TOC1SR) & IPCC_C2TOC1SR_BIT(chan)) != 0;
+}
+
+/****************************************************************************
+ * Name: stm32wb_ipcc_txactive
+ *
+ * Description:
+ *   Check channel transmit active flag.
+ *
+ ****************************************************************************/
+
+static inline bool stm32wb_ipcc_txactive(uint8_t chan)
+{
+  return (getreg32(STM32WB_IPCC_C1TOC2SR) & IPCC_C1TOC2SR_BIT(chan)) != 0;
+}
+
+/****************************************************************************
+ * Name: stm32wb_ipcc_settxactive
+ *
+ * Description:
+ *   Set channel transmit active flag.
+ *
+ ****************************************************************************/
+
+static inline void stm32wb_ipcc_settxactive(uint8_t chan)
+{
+  putreg32(IPCC_C1SCR_SET_BIT(chan), STM32WB_IPCC_C1SCR);
+}
+
+/****************************************************************************
+ * Name: stm32wb_ipcc_masktxf
+ *
+ * Description:
+ *   Mask channel transmit free interrupt.
+ *
+ ****************************************************************************/
+
+static inline void stm32wb_ipcc_masktxf(uint8_t chan)
+{
+  uint32_t regval = getreg32(STM32WB_IPCC_C1MR);
+  regval |= IPCC_C1MR_FM_BIT(chan);
+  putreg32(regval, STM32WB_IPCC_C1MR);
+}
+
+/****************************************************************************
+ * Name: stm32wb_ipcc_unmasktxf
+ *
+ * Description:
+ *   Unmask channel transmit free interrupt.
+ *
+ ****************************************************************************/
+
+static inline void stm32wb_ipcc_unmasktxf(uint8_t chan)
+{
+  uint32_t regval = getreg32(STM32WB_IPCC_C1MR);
+  regval &= ~IPCC_C1MR_FM_BIT(chan);
+  putreg32(regval, STM32WB_IPCC_C1MR);
+}
+
+/****************************************************************************
+ * Name: stm32wb_ipcc_maskrxo
+ *
+ * Description:
+ *   Mask channel receive occupied interrupt.
+ *
+ ****************************************************************************/
+
+static inline void stm32wb_ipcc_maskrxo(uint8_t chan)
+{
+  uint32_t regval = getreg32(STM32WB_IPCC_C1MR);
+  regval |= IPCC_C1MR_OM_BIT(chan);
+  putreg32(regval, STM32WB_IPCC_C1MR);
+}
+
+/****************************************************************************
+ * Name: stm32wb_ipcc_maskrxo
+ *
+ * Description:
+ *   Unmask channel receive occupied interrupt.
+ *
+ ****************************************************************************/
+
+static inline void stm32wb_ipcc_unmaskrxo(uint8_t chan)
+{
+  uint32_t regval = getreg32(STM32WB_IPCC_C1MR);
+  regval &= ~IPCC_C1MR_OM_BIT(chan);
+  putreg32(regval, STM32WB_IPCC_C1MR);
+}
+
 #undef EXTERN
 #if defined(__cplusplus)
 }
diff --git a/arch/arm/src/stm32wb/stm32wb_mbox.c b/arch/arm/src/stm32wb/stm32wb_mbox.c
new file mode 100644
index 0000000000..f3bed170a4
--- /dev/null
+++ b/arch/arm/src/stm32wb/stm32wb_mbox.c
@@ -0,0 +1,813 @@
+/****************************************************************************
+ * arch/arm/src/stm32wb/stm32wb_mbox.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 <assert.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/wqueue.h>
+
+#include "arm_internal.h"
+#include "stm32wb_ipcc.h"
+#include "stm32wb_mbox.h"
+#include "hardware/stm32wb_memorymap.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Mailbox shared buffer base address.  Normally it is located at
+ * the beginning of SRAM2a.
+ */
+
+#define STM32WB_MBOX_SHARED_BASE      STM32WB_SRAM2A_BASE
+
+/* Mailbox shared buffer fields */
+
+#define stm32wb_mbox_shared \
+  (*(struct stm32wb_mbox_shared_buffer_s *)STM32WB_MBOX_SHARED_BASE)
+
+#define stm32wb_mbox_ref_table        (stm32wb_mbox_shared.ref_table)
+#define stm32wb_mbox_di_table         (stm32wb_mbox_shared.dev_info_table)
+#define stm32wb_mbox_sys_table        (stm32wb_mbox_shared.sys_table)
+#define stm32wb_mbox_mm_table         (stm32wb_mbox_shared.mm_table)
+#define stm32wb_mbox_ble_table        (stm32wb_mbox_shared.ble_table)
+
+/* Mailbox buffer sizes */
+
+#define STM32WB_MBOX_CS_BUF_SIZE      16
+#define STM32WB_MBOX_CMDPKT_BUF_SIZE  268
+#define STM32WB_MBOX_ACLPKT_BUF_SIZE  264
+
+#define STM32WB_MBOX_RX_BUF_SIZE \
+  (CONFIG_STM32WB_MBOX_RX_EVT_QUEUE_LEN * STM32WB_MBOX_CMDPKT_BUF_SIZE)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* Mailbox shared buffer structures */
+
+begin_packed_struct struct stm32wb_mbox_safe_boot_info_table_s
+{
+  uint32_t  version;
+} end_packed_struct;
+
+begin_packed_struct struct stm32wb_mbox_fus_info_table_s
+{
+  uint32_t  version;
+  uint32_t  memory_size;
+  uint32_t  fus_info;
+} end_packed_struct;
+
+begin_packed_struct struct stm32wb_mbox_wireless_fw_info_table_s
+{
+  uint32_t  version;
+  uint32_t  memory_size;
+  uint32_t  info_stack;
+  uint32_t  reserved;
+} end_packed_struct;
+
+begin_packed_struct struct stm32wb_mbox_device_info_table_s
+{
+  struct stm32wb_mbox_safe_boot_info_table_s    safe_boot_info_table;
+  struct stm32wb_mbox_fus_info_table_s          fus_info_table;
+  struct stm32wb_mbox_wireless_fw_info_table_s  wireless_fw_info_table;
+} end_packed_struct;
+
+begin_packed_struct struct stm32wb_mbox_ble_table_s
+{
+  void      *cmd_buffer;
+  void      *cs_buffer;
+  void      *evt_queue;
+  void      *acl_buffer;
+} end_packed_struct;
+
+begin_packed_struct struct stm32wb_mbox_sys_table_s
+{
+  void      *cmd_buffer;
+  void      *evt_queue;
+} end_packed_struct;
+
+begin_packed_struct struct stm32wb_mbox_mem_manager_table_s
+{
+  void      *ble_spare_buffer;
+  void      *sys_spare_buffer;
+  void      *evtpool_buffer;
+  uint32_t  evtpool_size;
+  void      *evtfree_buffer;
+  void      *traces_evtpool_buffer;
+  uint32_t  traces_evtpool_size;
+} end_packed_struct;
+
+begin_packed_struct struct stm32wb_mbox_ref_table_s
+{
+  struct stm32wb_mbox_device_info_table_s   *dev_info_table;
+  struct stm32wb_mbox_ble_table_s           *ble_table;
+  void                                      *thread_table;
+  struct stm32wb_mbox_sys_table_s           *sys_table;
+  struct stm32wb_mbox_mem_manager_table_s   *mm_table;
+  void                                      *traces_table;
+  void                                      *mac_802_15_4_table;
+  void                                      *zigbee_table;
+  void                                      *ble_lld_test_table;
+  void                                      *ble_lld_table;
+} end_packed_struct;
+
+/* Mailbox shared buffer memory layout structure */
+
+struct stm32wb_mbox_shared_buffer_s
+{
+  aligned_data(4) struct stm32wb_mbox_ref_table_s         ref_table;
+
+  aligned_data(4) struct stm32wb_mbox_device_info_table_s dev_info_table;
+  aligned_data(4) struct stm32wb_mbox_ble_table_s         ble_table;
+  aligned_data(4) struct stm32wb_mbox_sys_table_s         sys_table;
+  aligned_data(4) struct stm32wb_mbox_mem_manager_table_s mm_table;
+
+  aligned_data(4) stm32wb_mbox_list_t  evtfree_buffer;
+#ifdef CONFIG_STM32WB_BLE
+  aligned_data(4) stm32wb_mbox_list_t  ble_evt_queue;
+#endif
+  aligned_data(4) stm32wb_mbox_list_t  sys_evt_queue;
+
+#ifdef CONFIG_STM32WB_BLE
+  aligned_data(4) uint8_t ble_cs_buffer[STM32WB_MBOX_CS_BUF_SIZE];
+#endif
+  aligned_data(4) uint8_t evtpool_buffer[STM32WB_MBOX_RX_BUF_SIZE];
+  aligned_data(4) uint8_t sys_cmd_buffer[STM32WB_MBOX_CMDPKT_BUF_SIZE];
+  aligned_data(4) uint8_t sys_spare_buffer[STM32WB_MBOX_CMDPKT_BUF_SIZE];
+#ifdef CONFIG_STM32WB_BLE
+  aligned_data(4) uint8_t ble_spare_buffer[STM32WB_MBOX_CMDPKT_BUF_SIZE];
+  aligned_data(4) uint8_t ble_cmd_buffer[STM32WB_MBOX_CMDPKT_BUF_SIZE];
+  aligned_data(4) uint8_t ble_acl_buffer[STM32WB_MBOX_ACLPKT_BUF_SIZE];
+#endif
+};
+
+/* Mailbox channel data type */
+
+struct stm32wb_mbox_channel_s
+{
+  uint8_t                     ch_num;
+  stm32wb_mbox_list_t         msg_buf_queue;
+  struct stm32wb_mbox_cmd_s   *msg_buf;
+  bool                        ack_ready;
+};
+
+/****************************************************************************
+ * Private Function prototypes
+ ****************************************************************************/
+
+static void stm32wb_ipcc_rxoisr(int irq, uint32_t *regs, void *arg);
+static void stm32wb_ipcc_txfisr(int irq, uint32_t *regs, void *arg);
+
+static void stm32wb_mbox_rxworker(void *arg);
+static void stm32wb_mbox_txworker(void *arg);
+
+static void stm32wb_mbox_eventfree(stm32wb_mbox_list_t *evt);
+static void stm32wb_mbox_acksyscmd(void);
+
+static int stm32wb_mbox_txdata(struct stm32wb_mbox_channel_s *chan,
+                               uint8_t type, void *data, size_t len);
+static bool stm32wb_mbox_txnext(struct stm32wb_mbox_channel_s *chan);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct work_s g_rx_evt_work;
+static struct work_s g_tx_cmd_work;
+
+static stm32wb_mbox_list_t g_rx_evt_queue;
+static stm32wb_mbox_list_t g_tx_evtfree_queue;
+static uint8_t g_free_buffers[CONFIG_STM32WB_MBOX_TX_CMD_QUEUE_LEN]
+                             [STM32WB_MBOX_CMDPKT_BUF_SIZE];
+static stm32wb_mbox_list_t g_free_buffers_pool;
+
+static struct stm32wb_mbox_channel_s g_syscmd_channel;
+#ifdef CONFIG_STM32WB_BLE
+static struct stm32wb_mbox_channel_s g_blecmd_channel;
+static struct stm32wb_mbox_channel_s g_bleacl_channel;
+#endif
+
+static stm32wb_mbox_evt_handler_t receive_evt_handler;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32wb_ipcc_rxoisr
+ *
+ * Description:
+ *   RX channel occupied interrupt handler (communication data posted
+ *   by sending processor).
+ *
+ ****************************************************************************/
+
+static void stm32wb_ipcc_rxoisr(int irq, uint32_t *regs, void *arg)
+{
+  uint32_t clrmask = 0;
+
+  /* Pull events from system channel into processing queue */
+
+  if (stm32wb_ipcc_rxactive(STM32WB_MBOX_SYSEVT_CHANNEL))
+    {
+      stm32wb_mbox_list_moveall(&stm32wb_mbox_shared.sys_evt_queue,
+                                &g_rx_evt_queue);
+
+      clrmask |= IPCC_C1SCR_CLR_BIT(STM32WB_MBOX_SYSEVT_CHANNEL);
+    }
+
+#ifdef CONFIG_STM32WB_BLE
+
+  /* Pull events from BLE channel into processing queue */
+
+  if (stm32wb_ipcc_rxactive(STM32WB_MBOX_BLEEVT_CHANNEL))
+    {
+      stm32wb_mbox_list_moveall(&stm32wb_mbox_shared.ble_evt_queue,
+                                &g_rx_evt_queue);
+
+      clrmask |= IPCC_C1SCR_CLR_BIT(STM32WB_MBOX_BLEEVT_CHANNEL);
+    }
+#endif
+
+  /* Process collected events in the work queue */
+
+  if (work_available(&g_rx_evt_work))
+    {
+      work_queue(HPWORK, &g_rx_evt_work, stm32wb_mbox_rxworker, NULL, 0);
+    }
+
+  /* Clear active statuses */
+
+  putreg32(clrmask, STM32WB_IPCC_C1SCR);
+}
+
+/****************************************************************************
+ * Name: stm32wb_ipcc_txfisr
+ *
+ * Description:
+ *   TX channel free interrupt handler (communication data retrieved
+ *   by receiving processor).
+ *
+ ****************************************************************************/
+
+static void stm32wb_ipcc_txfisr(int irq, uint32_t *regs, void *arg)
+{
+  uint32_t c1mr = getreg32(STM32WB_IPCC_C1MR);
+  uint32_t txfsrc;
+
+  /* TXF interrupt can be triggered by not masked channels and active status
+   * of the source channel is cleared by CPU2. So we ignore masked and active
+   * channels and rise other C1MR bits to highlight needed channels.
+   */
+
+  txfsrc = ~(c1mr | (getreg32(STM32WB_IPCC_C1TOC2SR) << IPCC_C1MR_FM_SHIFT))
+           & IPCC_C1MR_FM_MASK;
+
+  /* Check if the release channel triggered the interrupt */
+
+  if (txfsrc & IPCC_C1MR_FM_BIT(STM32WB_MBOX_EVT_RELEASE_CHANNEL))
+    {
+      /* Move all released events (if any) into transmission mailbox */
+
+      if (!stm32wb_mbox_list_is_empty(&g_tx_evtfree_queue))
+        {
+          stm32wb_mbox_list_moveall(&g_tx_evtfree_queue,
+                                    &stm32wb_mbox_shared.evtfree_buffer);
+
+          /* Start release channel transmission */
+
+          stm32wb_ipcc_settxactive(STM32WB_MBOX_EVT_RELEASE_CHANNEL);
+        }
+    }
+
+  /* Check other channels, except the release channel */
+
+  if (txfsrc & ~IPCC_C1MR_FM_BIT(STM32WB_MBOX_EVT_RELEASE_CHANNEL))
+    {
+      /* Check if the system channel triggered the interrupt */
+
+      if (txfsrc & IPCC_C1MR_FM_BIT(STM32WB_MBOX_SYSCMD_CHANNEL))
+        {
+          /* System channel works in 'half-duplex' mode and acks
+           * immediately on each command before TXF, so it needs
+           * to process ack response before sending next command.
+           */
+
+          g_syscmd_channel.ack_ready = true;
+        }
+
+      /* Continue command processing in a work queue */
+
+      if (work_available(&g_tx_cmd_work))
+        {
+          work_queue(HPWORK, &g_tx_cmd_work, stm32wb_mbox_txworker, NULL, 0);
+        }
+    }
+
+  /* Mask triggered channels */
+
+  putreg32(c1mr | txfsrc, STM32WB_IPCC_C1MR);
+}
+
+/****************************************************************************
+ * Name: stm32wb_mbox_txworker
+ ****************************************************************************/
+
+static void stm32wb_mbox_txworker(void *arg)
+{
+  bool handled;
+
+  /* Process all queued commands if a dedicated channel is free */
+
+  do
+    {
+      handled = false;
+
+      if (!stm32wb_ipcc_txactive(STM32WB_MBOX_SYSCMD_CHANNEL))
+        {
+          /* Process ack response before send new command */
+
+          if (g_syscmd_channel.ack_ready)
+            {
+              stm32wb_mbox_acksyscmd();
+              g_syscmd_channel.ack_ready = false;
+            }
+
+          handled = stm32wb_mbox_txnext(&g_syscmd_channel);
+        }
+
+#ifdef CONFIG_STM32WB_BLE
+      if (!stm32wb_ipcc_txactive(STM32WB_MBOX_BLECMD_CHANNEL))
+        {
+          handled |= stm32wb_mbox_txnext(&g_blecmd_channel);
+        }
+
+      if (!stm32wb_ipcc_txactive(STM32WB_MBOX_BLEACL_CHANNEL))
+        {
+          handled |= stm32wb_mbox_txnext(&g_bleacl_channel);
+        }
+#endif
+    }
+  while (handled);
+}
+
+/****************************************************************************
+ * Name: stm32wb_mbox_rxworker
+ ****************************************************************************/
+
+static void stm32wb_mbox_rxworker(void *arg)
+{
+  stm32wb_mbox_list_t *evt;
+  irqstate_t flags;
+
+  while (1)
+    {
+      flags = enter_critical_section();
+
+      /* Pull an event from the queue */
+
+      evt = stm32wb_mbox_list_remove_head(&g_rx_evt_queue);
+
+      leave_critical_section(flags);
+
+      if (evt == NULL)
+        {
+          break;
+        }
+
+      /* Pass event to a callback function without a list header */
+
+      receive_evt_handler((struct stm32wb_mbox_evt_s *)(evt + 1));
+
+      /* Free completed event.  Released event needs to return to CPU2
+       * via release channel.
+       */
+
+      stm32wb_mbox_eventfree((stm32wb_mbox_list_t *)evt);
+    }
+}
+
+/****************************************************************************
+ * Name: stm32wb_mbox_txdata
+ *
+ * Description:
+ *   Send data over specified mailbox channel if possible.  If the
+ *   channel is busy then add a prepared packet into awaiting queue.
+ *
+ ****************************************************************************/
+
+static int stm32wb_mbox_txdata(struct stm32wb_mbox_channel_s *chan,
+                               uint8_t type, void *data, size_t len)
+{
+  irqstate_t flags;
+  struct stm32wb_mbox_cmd_s *pkt_buf;
+
+  flags = enter_critical_section();
+
+  /* To start transmission the channel needs to be free, there should be
+   * none of other waiting commands and none of unprocessed ack responses.
+   */
+
+  if (stm32wb_mbox_list_is_empty(&chan->msg_buf_queue) &&
+      !stm32wb_ipcc_txactive(chan->ch_num) && !chan->ack_ready)
+    {
+      /* Channel is ready, copy command into transmission buffer */
+
+      pkt_buf = chan->msg_buf;
+    }
+  else
+    {
+      /* Otherwise get temp buffer for command */
+
+      pkt_buf = (struct stm32wb_mbox_cmd_s *)
+                stm32wb_mbox_list_remove_head(&g_free_buffers_pool);
+    }
+
+  leave_critical_section(flags);
+
+  if (pkt_buf == NULL)
+    {
+      return -ENOBUFS;
+    }
+
+  pkt_buf->type = type;
+  memcpy(&pkt_buf->cmd_hdr, data, len);
+
+  if (pkt_buf == chan->msg_buf)
+    {
+      /* Command is ready in mailbox buffer, start transmission now */
+
+      stm32wb_ipcc_settxactive(chan->ch_num);
+
+      if (!stm32wb_mbox_list_is_empty(&chan->msg_buf_queue) ||
+          chan->ch_num == STM32WB_MBOX_SYSCMD_CHANNEL)
+        {
+          /* There are more commands awaiting, so unmask interrupt to get
+           * notified when channel gets ready to process a next one.
+           * And the system channel needs to check ack on completion.
+           */
+
+          stm32wb_ipcc_unmasktxf(chan->ch_num);
+        }
+    }
+  else
+    {
+      /* Command is in temp buffer, push it into queue */
+
+      flags = enter_critical_section();
+      stm32wb_mbox_list_add_tail(&chan->msg_buf_queue, &pkt_buf->list_hdr);
+      leave_critical_section(flags);
+
+      /* Unmask interrupt to get notified when channel gets free */
+
+      stm32wb_ipcc_unmasktxf(chan->ch_num);
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: stm32wb_mbox_txnext
+ *
+ * Description:
+ *   Send next command from the queue.
+ *
+ ****************************************************************************/
+
+static bool stm32wb_mbox_txnext(struct stm32wb_mbox_channel_s *chan)
+{
+  struct stm32wb_mbox_cmd_s *pkt_buf;
+
+  pkt_buf = (struct stm32wb_mbox_cmd_s *)
+            stm32wb_mbox_list_remove_head(&chan->msg_buf_queue);
+
+  if (pkt_buf != NULL)
+    {
+      chan->msg_buf->type = pkt_buf->type;
+
+      if (chan->ch_num == STM32WB_MBOX_BLEACL_CHANNEL)
+        {
+          memcpy(chan->msg_buf, &pkt_buf->acl_hdr,
+                 pkt_buf->acl_hdr.len);
+        }
+      else
+        {
+          memcpy(chan->msg_buf, &pkt_buf->cmd_hdr,
+                 pkt_buf->cmd_hdr.param_len);
+        }
+
+      /* Start transmission */
+
+      stm32wb_ipcc_settxactive(chan->ch_num);
+
+      if (!stm32wb_mbox_list_is_empty(&chan->msg_buf_queue))
+        {
+          /* Unmask TXF interrupt to get notified when completed */
+
+          stm32wb_ipcc_unmasktxf(chan->ch_num);
+        }
+
+      /* Put back to pool the freed command buffer */
+
+      stm32wb_mbox_list_add_tail(&g_free_buffers_pool, &pkt_buf->list_hdr);
+    }
+
+  return pkt_buf != NULL;
+}
+
+/****************************************************************************
+ * Name: stm32wb_mbox_eventfree
+ *
+ * Description:
+ *   Free handled mailbox event.
+ *
+ ****************************************************************************/
+
+static void stm32wb_mbox_eventfree(stm32wb_mbox_list_t *evt)
+{
+  irqstate_t flags;
+
+  flags = enter_critical_section();
+
+  /* Collect releasing events in the global list */
+
+  stm32wb_mbox_list_add_tail(&g_tx_evtfree_queue, evt);
+
+  /* Check if release channel is ready to process now */
+
+  if (!stm32wb_ipcc_txactive(STM32WB_MBOX_EVT_RELEASE_CHANNEL))
+    {
+      /* Move all collected events into transmission queue */
+
+      stm32wb_mbox_list_moveall(&g_tx_evtfree_queue,
+                                &stm32wb_mbox_shared.evtfree_buffer);
+
+      /* Start transmission */
+
+      stm32wb_ipcc_settxactive(STM32WB_MBOX_EVT_RELEASE_CHANNEL);
+    }
+  else
+    {
+      /* Unmask interrupt to get notified when channel gets free */
+
+      stm32wb_ipcc_unmasktxf(STM32WB_MBOX_EVT_RELEASE_CHANNEL);
+    }
+
+  leave_critical_section(flags);
+}
+
+/****************************************************************************
+ * Name: stm32wb_mbox_acksyscmd
+ *
+ * Description:
+ *   Send ACK response event for completed system command.
+ *
+ ****************************************************************************/
+
+static void stm32wb_mbox_acksyscmd(void)
+{
+  struct stm32wb_mbox_evt_s *evt;
+
+  /* System command ACK response is placed at the same address as the
+   * processed command but without a list header.
+   */
+
+  evt = (struct stm32wb_mbox_evt_s *)(&g_syscmd_channel.msg_buf);
+  evt->type = STM32WB_MBOX_SYSACK;
+
+  receive_evt_handler(evt);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32wb_mboxinitialize
+ *
+ * Description:
+ *   Initialize mailbox driver memory.
+ *
+ * Input Parameters:
+ *   evt_handler - the function to call on event receive
+ *
+ ****************************************************************************/
+
+void stm32wb_mboxinitialize(stm32wb_mbox_evt_handler_t evt_handler)
+{
+  int i;
+
+  /* Init mailbox shared data */
+
+  stm32wb_mbox_list_initialize(&stm32wb_mbox_shared.sys_evt_queue);
+  stm32wb_mbox_list_initialize(&stm32wb_mbox_shared.evtfree_buffer);
+#ifdef CONFIG_STM32WB_BLE
+  stm32wb_mbox_list_initialize(&stm32wb_mbox_shared.ble_evt_queue);
+#endif
+
+  stm32wb_mbox_ref_table.dev_info_table = &stm32wb_mbox_di_table;
+  stm32wb_mbox_ref_table.ble_table      = &stm32wb_mbox_ble_table;
+  stm32wb_mbox_ref_table.sys_table      = &stm32wb_mbox_sys_table;
+  stm32wb_mbox_ref_table.mm_table       = &stm32wb_mbox_mm_table;
+
+  stm32wb_mbox_sys_table.cmd_buffer = &stm32wb_mbox_shared.sys_cmd_buffer;
+  stm32wb_mbox_sys_table.evt_queue  = &stm32wb_mbox_shared.sys_evt_queue;
+
+  stm32wb_mbox_mm_table.evtpool_buffer   = &stm32wb_mbox_shared
+                                            .evtpool_buffer;
+  stm32wb_mbox_mm_table.evtpool_size     = sizeof(stm32wb_mbox_shared
+                                                  .evtpool_buffer);
+  stm32wb_mbox_mm_table.evtfree_buffer   = &stm32wb_mbox_shared
+                                            .evtfree_buffer;
+  stm32wb_mbox_mm_table.sys_spare_buffer = &stm32wb_mbox_shared
+                                            .sys_spare_buffer;
+#ifdef CONFIG_STM32WB_BLE
+  stm32wb_mbox_mm_table.ble_spare_buffer = &stm32wb_mbox_shared
+                                            .ble_spare_buffer;
+#endif
+
+#ifdef CONFIG_STM32WB_BLE
+  stm32wb_mbox_ble_table.cmd_buffer = &stm32wb_mbox_shared.ble_cmd_buffer;
+  stm32wb_mbox_ble_table.acl_buffer = &stm32wb_mbox_shared.ble_acl_buffer;
+  stm32wb_mbox_ble_table.cs_buffer  = &stm32wb_mbox_shared.ble_cs_buffer;
+  stm32wb_mbox_ble_table.evt_queue  = &stm32wb_mbox_shared.ble_evt_queue;
+#endif
+
+  /* Init system channel data */
+
+  g_syscmd_channel.ch_num =  STM32WB_MBOX_SYSCMD_CHANNEL;
+  g_syscmd_channel.msg_buf = (struct stm32wb_mbox_cmd_s *)
+                              stm32wb_mbox_shared.sys_cmd_buffer;
+  stm32wb_mbox_list_initialize(&g_syscmd_channel.msg_buf_queue);
+
+#ifdef CONFIG_STM32WB_BLE
+  /* Init BLE command channel data */
+
+  g_blecmd_channel.ch_num =  STM32WB_MBOX_BLECMD_CHANNEL;
+  g_blecmd_channel.msg_buf = (struct stm32wb_mbox_cmd_s *)
+                             stm32wb_mbox_shared.ble_cmd_buffer;
+  stm32wb_mbox_list_initialize(&g_blecmd_channel.msg_buf_queue);
+
+  /* Init BLE ACL channel data */
+
+  g_bleacl_channel.ch_num =  STM32WB_MBOX_BLEACL_CHANNEL;
+  g_bleacl_channel.msg_buf = (struct stm32wb_mbox_cmd_s *)
+                             stm32wb_mbox_shared.ble_cmd_buffer;
+  stm32wb_mbox_list_initialize(&g_bleacl_channel.msg_buf_queue);
+#endif
+
+  /* Init local (not shared) queues */
+
+  stm32wb_mbox_list_initialize(&g_rx_evt_queue);
+  stm32wb_mbox_list_initialize(&g_tx_evtfree_queue);
+
+  stm32wb_mbox_list_initialize(&g_free_buffers_pool);
+  for (i = 0; i < CONFIG_STM32WB_MBOX_TX_CMD_QUEUE_LEN; i++)
+    {
+      stm32wb_mbox_list_add_tail(&g_free_buffers_pool,
+                                 (stm32wb_mbox_list_t *)g_free_buffers[i]);
+    }
+
+  /* Set event receive function */
+
+  receive_evt_handler = evt_handler;
+}
+
+/****************************************************************************
+ * Name: stm32wb_mboxenable
+ *
+ * Description:
+ *   Enable mailbox hardware and start communication.  The CPU2 responses
+ *   with C2Ready event on success.
+ *
+ ****************************************************************************/
+
+void stm32wb_mboxenable(void)
+{
+  uint32_t regval;
+
+  /* Setup RXO and TXF interrupts */
+
+  irq_attach(STM32WB_IRQ_IPCCRX, (xcpt_t)stm32wb_ipcc_rxoisr, NULL);
+  up_enable_irq(STM32WB_IRQ_IPCCRX);
+
+  irq_attach(STM32WB_IRQ_IPCCTX, (xcpt_t)stm32wb_ipcc_txfisr, NULL);
+  up_enable_irq(STM32WB_IRQ_IPCCTX);
+
+  regval = getreg32(STM32WB_IPCC_C1CR);
+  regval |= IPCC_C1CR_RXOIE | IPCC_C1CR_TXFIE;
+  putreg32(regval, STM32WB_IPCC_C1CR);
+
+  /* Unmask system channel RXO interrupt.  Once CPU2 started we expect
+   * to receive C2READY event via system channel.
+   */
+
+  stm32wb_ipcc_unmaskrxo(STM32WB_MBOX_SYSEVT_CHANNEL);
+
+  /* Enable IPCC hardware and bootup CPU2 */
+
+  stm32wb_ipccenable();
+}
+
+/****************************************************************************
+ * Name: stm32wb_mbox_syscmd
+ *
+ * Description:
+ *   Send command over mailbox system channel.  Command data must be
+ *   prepended with HCI header.
+ *
+ ****************************************************************************/
+
+int stm32wb_mbox_syscmd(void *data, size_t len)
+{
+  return stm32wb_mbox_txdata(&g_syscmd_channel, STM32WB_MBOX_SYSCMD,
+                             data, len);
+}
+
+#ifdef CONFIG_STM32WB_BLE
+/****************************************************************************
+ * Name: stm32wb_mbox_blecmd
+ *
+ * Description:
+ *   Send command over mailbox BLE channel.  Command data must be
+ *   prepended with HCI header.
+ *
+ ****************************************************************************/
+
+int stm32wb_mbox_blecmd(void *data, size_t len)
+{
+  return stm32wb_mbox_txdata(&g_blecmd_channel, STM32WB_MBOX_HCICMD,
+                             data, len);
+}
+
+/****************************************************************************
+ * Name: stm32wb_mbox_bleacl
+ *
+ * Description:
+ *   Send BLE ACL data over mailbox BLE ACL channel.  Data must be
+ *   prepended with HCI ACL header.
+ *
+ ****************************************************************************/
+
+int stm32wb_mbox_bleacl(void *data, size_t len)
+{
+  return stm32wb_mbox_txdata(&g_bleacl_channel, STM32WB_MBOX_HCIACL,
+                             data, len);
+}
+
+/****************************************************************************
+ * Name: stm32wb_mbox_bleinit
+ *
+ * Description:
+ *   Initialize and start BLE subsystem with provided configuration params.
+ *
+ ****************************************************************************/
+
+void stm32wb_mbox_bleinit(struct stm32wb_shci_ble_init_cfg_s *params)
+{
+  struct bt_hci_cmd_hdr_s *cmd;
+
+  /* Just borrow a temporary free buffer for command data */
+
+  cmd = (struct bt_hci_cmd_hdr_s *)stm32wb_mbox_shared.sys_spare_buffer;
+
+  /* Prepare command data */
+
+  cmd->opcode = STM32WB_SHCI_BLE_INIT;
+  cmd->param_len = sizeof(*cmd);
+  memcpy(cmd + 1, params, sizeof(*params));
+
+  /* Send BLE init command to CPU2 */
+
+  stm32wb_mbox_syscmd(cmd, sizeof(*cmd) + sizeof(*params));
+
+  /* Unmask BLE event channel RXO interrupt */
+
+  stm32wb_ipcc_unmaskrxo(STM32WB_MBOX_BLEEVT_CHANNEL);
+}
+#endif /* CONFIG_STM32WB_BLE */
diff --git a/arch/arm/src/stm32wb/stm32wb_mbox.h b/arch/arm/src/stm32wb/stm32wb_mbox.h
new file mode 100644
index 0000000000..210bf1c6b0
--- /dev/null
+++ b/arch/arm/src/stm32wb/stm32wb_mbox.h
@@ -0,0 +1,174 @@
+/****************************************************************************
+ * arch/arm/src/stm32wb/stm32wb_mbox.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_ARM_SRC_STM32WB_STM32WB_MBOX_H
+#define __ARCH_ARM_SRC_STM32WB_STM32WB_MBOX_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+
+#include <nuttx/wireless/bluetooth/bt_hci.h>
+
+#include "stm32wb_mbox_list.h"
+#include "stm32wb_mbox_shci.h"
+
+/****************************************************************************
+ * Pre-Processor Declarations
+ ****************************************************************************/
+
+/* Mailbox channels */
+
+#define STM32WB_MBOX_BLEEVT_CHANNEL       1
+#define STM32WB_MBOX_BLECMD_CHANNEL       1
+#define STM32WB_MBOX_SYSEVT_CHANNEL       2
+#define STM32WB_MBOX_SYSCMD_CHANNEL       2
+#define STM32WB_MBOX_EVT_RELEASE_CHANNEL  4
+#define STM32WB_MBOX_BLEACL_CHANNEL       6
+
+/* Mailbox packet types */
+
+#define STM32WB_MBOX_HCICMD               0x01
+#define STM32WB_MBOX_HCIACL               0x02
+#define STM32WB_MBOX_HCIEVT               0x04
+#define STM32WB_MBOX_SYSCMD               0x10
+#define STM32WB_MBOX_SYSEVT               0x12
+#define STM32WB_MBOX_SYSACK               0xe0
+
+/* Mailbox configuration helpers */
+
+#define STM32WB_MBOX_BLE_ATT_DEFAULT_MTU  23
+#define STM32WB_MBOX_C2_MEM_BLOCK_SZ      32
+
+#define DIV_UP(a, b)    (((a) + (b) - 1) / (b))
+
+#define STM32WB_MBOX_DEFAULT_BLE_PREP_WRITE_NUM(max_mtu) \
+  (DIV_UP((max_mtu), STM32WB_MBOX_BLE_ATT_DEFAULT_MTU - 5) * 2)
+
+#define STM32WB_MBOX_DEFAULT_C2_MEM_BLOCK_NUM(max_mtu, max_conn, pw) \
+  ((pw) + ((max_conn) + 1) * (DIV_UP((max_mtu) + 4, STM32WB_MBOX_C2_MEM_BLOCK_SZ) + 2))
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* Mailbox data transfer packets */
+
+begin_packed_struct struct stm32wb_mbox_evt_s
+{
+  uint8_t                       type;
+  union
+    {
+      struct bt_hci_evt_hdr_s   evt_hdr;
+      struct bt_hci_acl_hdr_s   acl_hdr;
+    };
+} end_packed_struct;
+
+begin_packed_struct struct stm32wb_mbox_cmd_s
+{
+  stm32wb_mbox_list_t           list_hdr;
+  uint8_t                       type;
+  union
+  {
+    struct bt_hci_cmd_hdr_s     cmd_hdr;
+    struct bt_hci_acl_hdr_s     acl_hdr;
+  };
+} end_packed_struct;
+
+/* Mailbox receive event handler type */
+
+typedef int (*stm32wb_mbox_evt_handler_t)(struct stm32wb_mbox_evt_s *);
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32wb_mboxinitialize
+ *
+ * Description:
+ *   Initialize mailbox driver memory.
+ *
+ * Input Parameters:
+ *   evt_handler - the function to call on event receive
+ *
+ ****************************************************************************/
+
+void stm32wb_mboxinitialize(stm32wb_mbox_evt_handler_t evt_handler);
+
+/****************************************************************************
+ * Name: stm32wb_mboxenable
+ *
+ * Description:
+ *   Enable mailbox hardware and start communication.  The CPU2 responses
+ *   with C2Ready event on success.
+ *
+ ****************************************************************************/
+
+void stm32wb_mboxenable(void);
+
+/****************************************************************************
+ * Name: stm32wb_mbox_syscmd
+ *
+ * Description:
+ *   Send command over mailbox system channel.  Command data must be
+ *   prepended with HCI header.
+ *
+ ****************************************************************************/
+
+int stm32wb_mbox_syscmd(void *data, size_t len);
+
+/****************************************************************************
+ * Name: stm32wb_mbox_blecmd
+ *
+ * Description:
+ *   Send command over mailbox BLE channel.  Command data must be
+ *   prepended with HCI header.
+ *
+ ****************************************************************************/
+
+int stm32wb_mbox_blecmd(void *data, size_t len);
+
+/****************************************************************************
+ * Name: stm32wb_mbox_bleacl
+ *
+ * Description:
+ *   Send BLE ACL data over mailbox BLE ACL channel.  Data must be
+ *   prepended with HCI ACL header.
+ *
+ ****************************************************************************/
+
+int stm32wb_mbox_bleacl(void *data, size_t len);
+
+/****************************************************************************
+ * Name: stm32wb_mbox_bleinit
+ *
+ * Description:
+ *   Initialize and start BLE subsystem with provided configuration params.
+ *
+ ****************************************************************************/
+
+void stm32wb_mbox_bleinit(struct stm32wb_shci_ble_init_cfg_s *params);
+
+#endif /* __ARCH_ARM_SRC_STM32WB_STM32WB_MBOX_H */
diff --git a/arch/arm/src/stm32wb/stm32wb_mbox_list.h b/arch/arm/src/stm32wb/stm32wb_mbox_list.h
new file mode 100644
index 0000000000..6081476022
--- /dev/null
+++ b/arch/arm/src/stm32wb/stm32wb_mbox_list.h
@@ -0,0 +1,144 @@
+/****************************************************************************
+ * arch/arm/src/stm32wb/stm32wb_mbox_list.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_ARM_SRC_STM32WB_STM32WB_MBOX_LIST_H
+#define __ARCH_ARM_SRC_STM32WB_STM32WB_MBOX_LIST_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* This list implementation is similar to list_node, but prev and next
+ * fields are at opposite places and the struct is packed.  Also there is
+ * a new list_moveall function.
+ */
+
+begin_packed_struct struct stm32wb_mbox_list_s
+{
+  struct stm32wb_mbox_list_s *next;
+  struct stm32wb_mbox_list_s *prev;
+} end_packed_struct;
+
+typedef struct stm32wb_mbox_list_s stm32wb_mbox_list_t;
+
+/****************************************************************************
+ * Inline Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32wb_mbox_list_initialize
+ *
+ * Description:
+ *   Initialize internal fields.
+ *
+ ****************************************************************************/
+
+static inline void stm32wb_mbox_list_initialize(stm32wb_mbox_list_t *list)
+{
+  list->prev = list;
+  list->next = list;
+}
+
+/****************************************************************************
+ * Name: stm32wb_mbox_list_add_tail
+ *
+ * Description:
+ *   Add new node at the end of the list.
+ *
+ ****************************************************************************/
+
+static inline void stm32wb_mbox_list_add_tail(stm32wb_mbox_list_t *list,
+                                              stm32wb_mbox_list_t *item)
+{
+  item->prev       = list->prev;
+  item->next       = list;
+  list->prev->next = item;
+  list->prev       = item;
+}
+
+/****************************************************************************
+ * Name: stm32wb_mbox_list_remove_head
+ *
+ * Description:
+ *   Remove and return first node from the list head (if any).
+ *
+ ****************************************************************************/
+
+static inline stm32wb_mbox_list_t *
+stm32wb_mbox_list_remove_head(stm32wb_mbox_list_t *list)
+{
+  if (list->next != list)
+  {
+    stm32wb_mbox_list_t *item = list->next;
+    item->next->prev = item->prev;
+    item->prev->next = item->next;
+    item->prev       = NULL;
+    item->next       = NULL;
+    return item;
+  }
+  else
+  {
+    return NULL;
+  }
+}
+
+/****************************************************************************
+ * Name: stm32wb_mbox_list_is_empty
+ *
+ * Description:
+ *   Check if the list is empty.
+ *
+ ****************************************************************************/
+
+static inline bool stm32wb_mbox_list_is_empty(stm32wb_mbox_list_t *list)
+{
+  return (list->next == list);
+}
+
+/****************************************************************************
+ * Name: stm32wb_mbox_list_moveall
+ *
+ * Description:
+ *   Remove all nodes from source list and add them to the end of the
+ *   destination list.
+ *
+ ****************************************************************************/
+
+static inline void stm32wb_mbox_list_moveall(stm32wb_mbox_list_t *src,
+                                             stm32wb_mbox_list_t *dst)
+{
+  if (src->next != src)
+    {
+      src->next->prev = dst->prev;
+      src->prev->next = dst;
+      dst->prev->next = src->next;
+      dst->prev       = src->prev;
+      src->prev       = src;
+      src->next       = src;
+    }
+}
+
+#endif /* __ARCH_ARM_SRC_STM32WB_STM32WB_MBOX_LIST_H */
diff --git a/arch/arm/src/stm32wb/stm32wb_mbox_shci.h b/arch/arm/src/stm32wb/stm32wb_mbox_shci.h
new file mode 100644
index 0000000000..7ca109fda5
--- /dev/null
+++ b/arch/arm/src/stm32wb/stm32wb_mbox_shci.h
@@ -0,0 +1,186 @@
+/****************************************************************************
+ * arch/arm/src/stm32wb/stm32wb_mbox_shci.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_ARM_SRC_STM32WB_STM32WB_MBOX_SHCI_H
+#define __ARCH_ARM_SRC_STM32WB_STM32WB_MBOX_SHCI_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <nuttx/compiler.h>
+
+/****************************************************************************
+ * Pre-Processor Declarations
+ ****************************************************************************/
+
+/* SHCI event types *********************************************************/
+
+#define STM32WB_SHCI_ASYNC_EVT              0xff
+
+/* SHCI async event subtypes */
+
+#define STM32WB_SHCI_ASYNC_EVT_C2RDY        0x9200
+
+/* SHCI system command acknowledgement events */
+
+#define STM32WB_SHCI_ACK_EVT_C2RDY          0x05
+
+/* SHCI command opcodes *****************************************************/
+
+#define STM32WB_SHCI_OGF                    0x3f
+#define STM32WB_SHCI_OP(ogf, ocf)           (((ogf) << 10) | (ocf))
+
+#define STM32WB_SHCI_FUS_GET_STATE          STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x52)
+#define STM32WB_SHCI_FUS_FW_UPGRADE         STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x54)
+#define STM32WB_SHCI_FUS_FW_DELETE          STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x55)
+#define STM32WB_SHCI_FUS_UPDATE_AUTH_KEY    STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x56)
+#define STM32WB_SHCI_FUS_LOCK_AUTH_KEY      STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x57)
+#define STM32WB_SHCI_FUS_STORE_USR_KEY      STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x58)
+#define STM32WB_SHCI_FUS_LOAD_USR_KEY       STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x59)
+#define STM32WB_SHCI_FUS_START_WS           STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x5a)
+#define STM32WB_SHCI_FUS_LOCK_USR_KEY       STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x5d)
+#define STM32WB_SHCI_FUS_UNLOAD_USR_KEY     STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x5e)
+#define STM32WB_SHCI_FUS_ANTIROLLBACK       STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x5f)
+#define STM32WB_SHCI_BLE_INIT               STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x66)
+#define STM32WB_SHCI_THREAD_INIT            STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x67)
+#define STM32WB_SHCI_DEBUG_INIT             STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x68)
+#define STM32WB_SHCI_FLASH_ERASE_ACTIVITY   STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x69)
+#define STM32WB_SHCI_CONCURRENT_SET_MODE    STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x6a)
+#define STM32WB_SHCI_FLASH_STORE_DATA       STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x6b)
+#define STM32WB_SHCI_FLASH_ERASE_DATA       STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x6c)
+#define STM32WB_SHCI_RADIO_ALLOW_LOW_POWER  STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x6d)
+#define STM32WB_SHCI_MAC_802154_INIT        STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x6e)
+#define STM32WB_SHCI_REINIT                 STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x6f)
+#define STM32WB_SHCI_ZIGBEE_INIT            STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x70)
+#define STM32WB_SHCI_LLD_TESTS_INIT         STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x71)
+#define STM32WB_SHCI_EXTPA_CONFIG           STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x72)
+#define STM32WB_SHCI_SET_FLASH_CONTROL      STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x73)
+#define STM32WB_SHCI_BLE_LLD_INIT           STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x74)
+#define STM32WB_SHCI_CONFIG                 STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x75)
+#define STM32WB_SHCI_GET_NEXT_BLE_EVT_TIME  STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x76)
+#define STM32WB_SHCI_ENABLE_NEXT_802154_NF  STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x77)
+#define STM32WB_SHCI_802_15_4_DEINIT        STM32WB_SHCI_OP(STM32WB_SHCI_OGF, 0x78)
+
+/* Command params bitfield definitions **************************************/
+
+/* BLE init command option flags */
+
+#define STM32WB_SHCI_BLE_INIT_OPT_STACK_MASK              (1 << 0) /* Bit 0: BLE stack select */
+#  define STM32WB_SHCI_BLE_INIT_OPT_STACK_LL_HOST         (0 << 0) /* 0x0: Link Layer and Host */
+#  define STM32WB_SHCI_BLE_INIT_OPT_STACK_LL              (1 << 0) /* 0x1: Link Layer only */
+
+#define STM32WB_SHCI_BLE_INIT_OPT_SVC_CHCHAR_MASK         (1 << 1) /* Bit 1: Service Changed characteristic */
+#  define STM32WB_SHCI_BLE_INIT_OPT_SVC_CHCHAR_ENABLED    (0 << 1) /* 0x0: Characteristic enabled */
+#  define STM32WB_SHCI_BLE_INIT_OPT_SVC_CHCHAR_DISABLED   (1 << 1) /* 0x1: Characteristic disabled */
+
+#define STM32WB_SHCI_BLE_INIT_OPT_DEVICE_NAME_MODE_MASK   (1 << 2) /* Bit 2: Device Name mode */
+#  define STM32WB_SHCI_BLE_INIT_OPT_DEVICE_NAME_MODE_RW   (0 << 2) /* 0x0: Read-Write mode */
+#  define STM32WB_SHCI_BLE_INIT_OPT_DEVICE_NAME_MODE_RO   (1 << 2) /* 0x1: Read-Only mode */
+
+#define STM32WB_SHCI_BLE_INIT_OPT_CS_ALG2_MASK            (1 << 4) /* Bit 4: Channel selection algorithm 2 enabled */
+#  define STM32WB_SHCI_BLE_INIT_OPT_CS_ALG2_DISABLED      (0 << 4) /* 0x0: Algorithm 2 disabled */
+#  define STM32WB_SHCI_BLE_INIT_OPT_CS_ALG2_ENABLED       (1 << 4) /* 0x1: Algorithm 2 enabled */
+
+#define STM32WB_SHCI_BLE_INIT_OPT_POWER_CLASS_MASK        (1 << 7) /* Bit 7: Power class */
+#  define STM32WB_SHCI_BLE_INIT_OPT_POWER_CLASS_2_3       (0 << 7) /* 0x0: Power Class 2-3 */
+#  define STM32WB_SHCI_BLE_INIT_OPT_POWER_CLASS_1         (1 << 7) /* 0x1: Power Class 1 */
+
+/* BLE init command rx_model_config flags */
+
+#define STM32WB_SHCI_BLE_INIT_RXMOD_AGC_RSSI_MASK         (1 << 0) /* Bit 0: AGC RSSI model */
+#  define STM32WB_SHCI_BLE_INIT_RXMOD_AGC_RSSI_LEGACY     (0 << 0) /* 0x0: AGC RSSI Legacy */
+#  define STM32WB_SHCI_BLE_INIT_RXMOD_AGC_RSSI_IMPROVED   (1 << 0) /* 0x1: AGC RSSI Improved */
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* STM32WB_SHCI_BLE_INIT command params */
+
+begin_packed_struct struct stm32wb_shci_ble_init_cfg_s
+{
+  void     *ble_buf;              /* Not used, must be NULL. */
+  uint32_t ble_buf_size;          /* Not used, must be 0. */
+
+  uint16_t gatt_attr_num;         /* Maximum number of GATT attributes. */
+  uint16_t gatt_srv_num;          /* Maximum number of GATT services. */
+  uint16_t gatt_attr_buf_size;    /* GATT attributes storage buf size. */
+
+  uint8_t  max_conn;              /* Maximum number of simultaneous
+                                   * connections, up to 8 is supported. */
+
+  uint8_t  dle_enable;            /* Data Length Extension enable. */
+
+  uint8_t  prep_write_op_num;     /* Maximum number of Prepare Write
+                                   * operations. */
+
+  uint8_t  mem_block_num;         /* Number of allocated memory blocks,
+                                   * throughput performance / memory usage
+                                   * tuning. */
+
+  uint16_t att_max_mtu_size;      /* Maximum attribute MTU size. */
+
+  uint16_t slave_sca;             /* Sleep clock accuracy (ppm value) in
+                                   * slave mode. */
+
+  uint8_t  master_sca_range;      /* Sleep clock accuracy in master mode:
+                                   * 0x00: 251 ppm to 500 ppm
+                                   * 0x01: 151 ppm to 250 ppm
+                                   * 0x02: 101 ppm to 150 ppm
+                                   * 0x03: 76 ppm to 100 ppm
+                                   * 0x04: 51 ppm to 75 ppm
+                                   * 0x05: 31 ppm to 50 ppm
+                                   * 0x06: 21 ppm to 30 ppm
+                                   * 0x07: 0 ppm to 20 ppm */
+
+  uint8_t  ls_clock_source;       /* Low speed 32 kHz clock source:
+                                   * 0x00: use LSE
+                                   * 0x01: use HSE */
+
+  uint32_t conn_event_length;     /* Maximum duration of a slave connection
+                                   * event in units of 625/256us
+                                   * (~2.44us). */
+
+  uint16_t hse_startup;           /* HSE startup time in units of 625/256us
+                                   * (~2.44us). */
+
+  uint8_t  viterbi_enable;        /* Enable Viterbi algorithm
+                                   * implementation. */
+
+  uint8_t  options;               /* BLE init option flags. */
+
+  uint8_t  hw_version;            /* Not used, must be 0. */
+
+  uint8_t  max_initor_coc_num;    /* Maximum number of connection-oriented
+                                   * channels in initiator mode. */
+
+  int8_t   tx_power_min;          /* Minimum transmit power in dBm.
+                                   * Range: -127 .. 20 */
+
+  int8_t   tx_power_max;          /* Maximum transmit power in dBm.
+                                   * Range: -127 .. 20 */
+
+  uint8_t  rx_model_config;       /* RX model config flags */
+} end_packed_struct;
+
+#endif /* __ARCH_ARM_SRC_STM32WB_STM32WB_MBOX_SHCI_H */
diff --git a/arch/arm/src/stm32wb/stm32wb_rcc.c b/arch/arm/src/stm32wb/stm32wb_rcc.c
index d268009732..44b3fe4e10 100644
--- a/arch/arm/src/stm32wb/stm32wb_rcc.c
+++ b/arch/arm/src/stm32wb/stm32wb_rcc.c
@@ -810,6 +810,17 @@ static void stm32wb_stdclockconfig(void)
       putreg32(regval, STM32WB_RCC_CR);
 #  endif
 #endif /* STM32WB_USE_LSE */
+
+      /* Select CPU2 RF wakeup clock source, no clock if not set */
+
+      regval  = getreg32(STM32WB_RCC_CSR);
+      regval &= ~RCC_CSR_RFWKPSEL_MASK;
+#if defined(STM32WB_BOARD_RFWKP_USELSE)
+      regval |= RCC_CSR_RFWKPSEL_LSE;
+#elif defined(STM32WB_BOARD_RFWKP_USEHSE)
+      regval |= RCC_CSR_RFWKPSEL_HSE;
+#endif
+      putreg32(regval, STM32WB_RCC_CSR);
     }
 }
 #endif
diff --git a/boards/arm/stm32wb/nucleo-wb55rg/README.txt b/boards/arm/stm32wb/nucleo-wb55rg/README.txt
index d0228bb114..f9fc90530e 100644
--- a/boards/arm/stm32wb/nucleo-wb55rg/README.txt
+++ b/boards/arm/stm32wb/nucleo-wb55rg/README.txt
@@ -26,6 +26,8 @@ Status
     supported - GPIO, EXTI, DMA, timers, flash, PWR, RTC, USART/LPUART, SPI,
     IPCC. SRAM2 heap allocation works. Builtin apps work and ostest passed.
 
+  July 2022: Added BLE support with mailbox IPC driver.
+
 LEDs
 ====
 
@@ -60,3 +62,8 @@ Configurations
 
     Configures the NuttShell (nsh) located at examples/nsh.  This
     configuration is focused on low level, command-line driver testing.
+
+  ble:
+
+    Besides the NuttShell this configuration also enables BLE support.
+    It includes btsak application for testing BLE applications.
diff --git a/boards/arm/stm32wb/nucleo-wb55rg/configs/ble/defconfig b/boards/arm/stm32wb/nucleo-wb55rg/configs/ble/defconfig
new file mode 100644
index 0000000000..dca33bff35
--- /dev/null
+++ b/boards/arm/stm32wb/nucleo-wb55rg/configs/ble/defconfig
@@ -0,0 +1,55 @@
+#
+# 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_NET_IPv4 is not set
+CONFIG_ALLOW_BSD_COMPONENTS=y
+CONFIG_ARCH="arm"
+CONFIG_ARCH_BOARD="nucleo-wb55rg"
+CONFIG_ARCH_BOARD_NUCLEO_WB55RG=y
+CONFIG_ARCH_CHIP="stm32wb"
+CONFIG_ARCH_CHIP_STM32WB55RG=y
+CONFIG_ARCH_CHIP_STM32WB=y
+CONFIG_ARCH_INTERRUPTSTACK=2048
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_BOARD_LOOPSPERMSEC=6500
+CONFIG_BTSAK=y
+CONFIG_BUILTIN=y
+CONFIG_DEBUG_SYMBOLS=y
+CONFIG_DRIVERS_BLUETOOTH=y
+CONFIG_DRIVERS_WIRELESS=y
+CONFIG_FS_PROCFS=y
+CONFIG_HAVE_CXX=y
+CONFIG_HAVE_CXXINITIALIZE=y
+CONFIG_INIT_ENTRYPOINT="nsh_main"
+CONFIG_INTELHEX_BINARY=y
+CONFIG_NET=y
+CONFIG_NET_BLUETOOTH=y
+CONFIG_NET_STATISTICS=y
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_DISABLE_IFUPDOWN=y
+CONFIG_NSH_FILEIOSIZE=512
+CONFIG_NSH_LINELEN=64
+CONFIG_NSH_READLINE=y
+CONFIG_PREALLOC_MQ_MSGS=32
+CONFIG_PREALLOC_TIMERS=4
+CONFIG_RAM_SIZE=196608
+CONFIG_RAM_START=0x20000000
+CONFIG_RAW_BINARY=y
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_WAITPID=y
+CONFIG_STM32WB_BLE=y
+CONFIG_STM32WB_DISABLE_IDLE_SLEEP_DURING_DEBUG=y
+CONFIG_STM32WB_DMA1=y
+CONFIG_STM32WB_PWR=y
+CONFIG_STM32WB_USART1=y
+CONFIG_SYSTEM_NSH=y
+CONFIG_TASK_NAME_SIZE=0
+CONFIG_TESTING_OSTEST=y
+CONFIG_USART1_SERIAL_CONSOLE=y
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_BLUETOOTH=y
diff --git a/boards/arm/stm32wb/nucleo-wb55rg/include/nucleo-wb55rg.h b/boards/arm/stm32wb/nucleo-wb55rg/include/nucleo-wb55rg.h
index c2fc3aacf9..79ae8bb8c4 100644
--- a/boards/arm/stm32wb/nucleo-wb55rg/include/nucleo-wb55rg.h
+++ b/boards/arm/stm32wb/nucleo-wb55rg/include/nucleo-wb55rg.h
@@ -69,6 +69,12 @@
 #  define MSI_CLOCK_CONFIG              1 /* MSI @ 4MHz autotrimmed via LSE */
 #endif
 
+#if 0
+#  define STM32WB_BOARD_RFWKP_USEHSE    1 /* CPU2 use HSE/1024 on RF wakeup */
+#elif 1
+#  define STM32WB_BOARD_RFWKP_USELSE    1 /* CPU2 use LSE on RF wakeup */
+#endif
+
 #if defined(HSI_CLOCK_CONFIG)
 
 #define STM32WB_BOARD_USEHSI            1
diff --git a/boards/arm/stm32wb/nucleo-wb55rg/src/stm32_appinit.c b/boards/arm/stm32wb/nucleo-wb55rg/src/stm32_appinit.c
index d505e8b887..497284720e 100644
--- a/boards/arm/stm32wb/nucleo-wb55rg/src/stm32_appinit.c
+++ b/boards/arm/stm32wb/nucleo-wb55rg/src/stm32_appinit.c
@@ -43,6 +43,12 @@
 #  include "stm32wb_rtc.h"
 #endif
 
+#ifdef CONFIG_STM32WB_BLE
+#  include "stm32wb_blehci.h"
+#endif
+
+#include "nucleo-wb55rg.h"
+
 /****************************************************************************
  * Private Data
  ****************************************************************************/
@@ -51,6 +57,20 @@
  * Public Functions
  ****************************************************************************/
 
+/****************************************************************************
+ * Name: arm_netinitialize
+ *
+ * Description:
+ *   Dummy function expected to start-up logic.
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_NET) && !defined(CONFIG_NETDEV_LATEINIT)
+void arm_netinitialize(void)
+{
+}
+#endif
+
 /****************************************************************************
  * Name: board_app_initialize
  *
@@ -135,6 +155,12 @@ int board_app_initialize(uintptr_t arg)
     }
 #endif
 
+#ifdef CONFIG_STM32WB_BLE
+  /* Initialize and register BLE HCI driver */
+
+  stm32wb_blehci_initialize();
+#endif
+
   return ret;
 }
 #endif /* CONFIG_BOARDCTL */