diff --git a/examples/Central/LedControl/LedControl.ino b/examples/Central/LedControl/LedControl.ino
index 4eec9259..2b916c53 100644
--- a/examples/Central/LedControl/LedControl.ino
+++ b/examples/Central/LedControl/LedControl.ino
@@ -28,6 +28,11 @@ SPIClass SpiHCI(PC12, PC11, PC10);
HCISpiTransportClass HCISpiTransport(SpiHCI, SPBTLE_RF, PD13, PE6, PA8, 8000000, SPI_MODE0);
BLELocalDevice BLE(&HCISpiTransport);
const int buttonPin = PC13; // set buttonPin to digital pin PC13
+#elif defined(ARDUINO_PNUCLEO_WB55RG)
+/* PNUCLEO_WB55RG */
+HCISharedMemTransportClass HCISharedMemTransport;
+BLELocalDevice BLE(&HCISharedMemTransport);
+const int buttonPin = PC4; // set buttonPin to digital pin PC4
#else
/* Shield IDB05A2 with SPI clock on D3 */
SPIClass SpiHCI(D11, D12, D3);
diff --git a/examples/Central/PeripheralExplorer/PeripheralExplorer.ino b/examples/Central/PeripheralExplorer/PeripheralExplorer.ino
index 5f33e4bd..5d5da6a3 100644
--- a/examples/Central/PeripheralExplorer/PeripheralExplorer.ino
+++ b/examples/Central/PeripheralExplorer/PeripheralExplorer.ino
@@ -25,6 +25,10 @@ BLELocalDevice BLE(&HCISpiTransport);
SPIClass SpiHCI(PC12, PC11, PC10);
HCISpiTransportClass HCISpiTransport(SpiHCI, SPBTLE_RF, PD13, PE6, PA8, 8000000, SPI_MODE0);
BLELocalDevice BLE(&HCISpiTransport);
+#elif defined(ARDUINO_PNUCLEO_WB55RG)
+/* PNUCLEO_WB55RG */
+HCISharedMemTransportClass HCISharedMemTransport;
+BLELocalDevice BLE(&HCISharedMemTransport);
#else
/* Shield IDB05A2 with SPI clock on D3 */
SPIClass SpiHCI(D11, D12, D3);
diff --git a/examples/Central/Scan/Scan.ino b/examples/Central/Scan/Scan.ino
index 30e382e5..8d1357b3 100644
--- a/examples/Central/Scan/Scan.ino
+++ b/examples/Central/Scan/Scan.ino
@@ -22,6 +22,10 @@ BLELocalDevice BLE(&HCISpiTransport);
SPIClass SpiHCI(PC12, PC11, PC10);
HCISpiTransportClass HCISpiTransport(SpiHCI, SPBTLE_RF, PD13, PE6, PA8, 8000000, SPI_MODE0);
BLELocalDevice BLE(&HCISpiTransport);
+#elif defined(ARDUINO_PNUCLEO_WB55RG)
+/* PNUCLEO_WB55RG */
+HCISharedMemTransportClass HCISharedMemTransport;
+BLELocalDevice BLE(&HCISharedMemTransport);
#else
/* Shield IDB05A2 with SPI clock on D3 */
SPIClass SpiHCI(D11, D12, D3);
diff --git a/examples/Central/ScanCallback/ScanCallback.ino b/examples/Central/ScanCallback/ScanCallback.ino
index e7c1711e..0cf28c57 100644
--- a/examples/Central/ScanCallback/ScanCallback.ino
+++ b/examples/Central/ScanCallback/ScanCallback.ino
@@ -24,6 +24,10 @@ BLELocalDevice BLE(&HCISpiTransport);
SPIClass SpiHCI(PC12, PC11, PC10);
HCISpiTransportClass HCISpiTransport(SpiHCI, SPBTLE_RF, PD13, PE6, PA8, 8000000, SPI_MODE0);
BLELocalDevice BLE(&HCISpiTransport);
+#elif defined(ARDUINO_PNUCLEO_WB55RG)
+/* PNUCLEO_WB55RG */
+HCISharedMemTransportClass HCISharedMemTransport;
+BLELocalDevice BLE(&HCISharedMemTransport);
#else
/* Shield IDB05A2 with SPI clock on D3 */
SPIClass SpiHCI(D11, D12, D3);
diff --git a/examples/Central/SensorTagButton/SensorTagButton.ino b/examples/Central/SensorTagButton/SensorTagButton.ino
index 0fdfdb13..fdb469d3 100644
--- a/examples/Central/SensorTagButton/SensorTagButton.ino
+++ b/examples/Central/SensorTagButton/SensorTagButton.ino
@@ -26,6 +26,10 @@ BLELocalDevice BLE(&HCISpiTransport);
SPIClass SpiHCI(PC12, PC11, PC10);
HCISpiTransportClass HCISpiTransport(SpiHCI, SPBTLE_RF, PD13, PE6, PA8, 8000000, SPI_MODE0);
BLELocalDevice BLE(&HCISpiTransport);
+#elif defined(ARDUINO_PNUCLEO_WB55RG)
+/* PNUCLEO_WB55RG */
+HCISharedMemTransportClass HCISharedMemTransport;
+BLELocalDevice BLE(&HCISharedMemTransport);
#else
/* Shield IDB05A2 with SPI clock on D3 */
SPIClass SpiHCI(D11, D12, D3);
diff --git a/examples/Peripheral/ButtonLED/ButtonLED.ino b/examples/Peripheral/ButtonLED/ButtonLED.ino
index e343fb26..a84fbd92 100644
--- a/examples/Peripheral/ButtonLED/ButtonLED.ino
+++ b/examples/Peripheral/ButtonLED/ButtonLED.ino
@@ -29,6 +29,11 @@ SPIClass SpiHCI(PC12, PC11, PC10);
HCISpiTransportClass HCISpiTransport(SpiHCI, SPBTLE_RF, PD13, PE6, PA8, 8000000, SPI_MODE0);
BLELocalDevice BLE(&HCISpiTransport);
const int buttonPin = PC13; // set buttonPin to digital pin PC13
+#elif defined(ARDUINO_PNUCLEO_WB55RG)
+/* PNUCLEO_WB55RG */
+HCISharedMemTransportClass HCISharedMemTransport;
+BLELocalDevice BLE(&HCISharedMemTransport);
+const int buttonPin = PC4; // set buttonPin to digital pin PC4
#else
/* Shield IDB05A2 with SPI clock on D3 */
SPIClass SpiHCI(D11, D12, D3);
diff --git a/examples/Peripheral/CallbackLED/CallbackLED.ino b/examples/Peripheral/CallbackLED/CallbackLED.ino
index 44be0e39..b1d5da94 100644
--- a/examples/Peripheral/CallbackLED/CallbackLED.ino
+++ b/examples/Peripheral/CallbackLED/CallbackLED.ino
@@ -27,6 +27,10 @@ BLELocalDevice BLE(&HCISpiTransport);
SPIClass SpiHCI(PC12, PC11, PC10);
HCISpiTransportClass HCISpiTransport(SpiHCI, SPBTLE_RF, PD13, PE6, PA8, 8000000, SPI_MODE0);
BLELocalDevice BLE(&HCISpiTransport);
+#elif defined(ARDUINO_PNUCLEO_WB55RG)
+/* PNUCLEO_WB55RG */
+HCISharedMemTransportClass HCISharedMemTransport;
+BLELocalDevice BLE(&HCISharedMemTransport);
#else
/* Shield IDB05A2 with SPI clock on D3 */
SPIClass SpiHCI(D11, D12, D3);
diff --git a/examples/Peripheral/LED/LED.ino b/examples/Peripheral/LED/LED.ino
index 8269bfcc..d7748474 100644
--- a/examples/Peripheral/LED/LED.ino
+++ b/examples/Peripheral/LED/LED.ino
@@ -25,6 +25,10 @@ BLELocalDevice BLE(&HCISpiTransport);
SPIClass SpiHCI(PC12, PC11, PC10);
HCISpiTransportClass HCISpiTransport(SpiHCI, SPBTLE_RF, PD13, PE6, PA8, 8000000, SPI_MODE0);
BLELocalDevice BLE(&HCISpiTransport);
+#elif defined(ARDUINO_PNUCLEO_WB55RG)
+/* PNUCLEO_WB55RG */
+HCISharedMemTransportClass HCISharedMemTransport;
+BLELocalDevice BLE(&HCISharedMemTransport);
#else
/* Shield IDB05A2 with SPI clock on D3 */
SPIClass SpiHCI(D11, D12, D3);
diff --git a/src/STM32duinoBLE.h b/src/STM32duinoBLE.h
index b5fa9b54..4bf51468 100644
--- a/src/STM32duinoBLE.h
+++ b/src/STM32duinoBLE.h
@@ -24,6 +24,10 @@
#include "BLEProperty.h"
#include "BLEStringCharacteristic.h"
#include "BLETypedCharacteristics.h"
+
+#if defined(STM32WBxx)
+#include "utility/HCISharedMemTransport.h"
+#endif
#include "utility/HCISpiTransport.h"
#endif
diff --git a/src/utility/HCISharedMemTransport.cpp b/src/utility/HCISharedMemTransport.cpp
new file mode 100644
index 00000000..c798fe74
--- /dev/null
+++ b/src/utility/HCISharedMemTransport.cpp
@@ -0,0 +1,734 @@
+/*
+ This file is part of the STM32duinoBLE library.
+ Copyright (c) 2019 STMicroelectronics. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#if defined(STM32WBxx)
+
+#include "HCISharedMemTransport.h"
+#include "STM32Cube_FW/hw.h"
+
+/* Private variables ---------------------------------------------------------*/
+PLACE_IN_SECTION("MB_MEM1") ALIGN(4) static TL_CmdPacket_t BleCmdBuffer;
+
+PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t EvtPool[POOL_SIZE];
+PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static TL_CmdPacket_t SystemCmdBuffer;
+PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t
+SystemSpareEvtBuffer[sizeof(TL_PacketHeader_t) + TL_EVT_HDR_SIZE + 255];
+PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t
+BleSpareEvtBuffer[sizeof(TL_PacketHeader_t) + TL_EVT_HDR_SIZE + 255];
+PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t
+HciAclDataBuffer[sizeof(TL_PacketHeader_t) + 5 + 251];
+
+
+/* global var used as semaphore to control incoming events */
+volatile bool sys_event; /* true : M0 core is already up and running */
+volatile bool acl_data_on; /* true : sending ACL data in progress, false : send is possible */
+volatile bool data_overflow;
+
+/* buffer to store the received packets */
+volatile uint8_t _rxbuff[BLE_MODULE_SHARED_MEM_BUFFER_SIZE];
+volatile uint16_t _read_index; /* fifo position when reading */
+volatile uint16_t _write_index; /* fifo position when receiving */
+
+/* var of different device steps during init and receiving */
+volatile bool phase_bd_addr;
+volatile bool phase_tx_power;
+volatile bool phase_reset;
+volatile bool phase_running;
+
+/** Bluetooth Device Address */
+static uint8_t bd_addr_udn[CONFIG_DATA_PUBADDR_LEN];
+
+/* Private functions ---------------------------------------------------------*/
+/**
+ * TL Mailbox synchronisation means
+ */
+
+/* returns true if sys_event was received, false otherwise */
+static bool sysevt_wait(void)
+{
+ /* sys_event remains false until event is received */
+ for (unsigned long start = millis(); (millis() - start) < BLE_IPCC_TIMEOUT;) {
+ /* Wait for 10sec max - if not return an error */
+ if (sys_event) {
+ break;
+ }
+ }
+
+ if (!sys_event) {
+#if defined(PRINT_IPCC_INFO)
+ printf("ERROR: sys_evt timeout\r\n");
+#endif /*(PRINT_IPCC_INFO)*/
+ /* no event received, timeout occurs */
+ return false;
+ }
+ /* release immediately, now that M0 runs */
+ return true;
+}
+
+/* WEAK callbacks from the BLE TL driver - will be called under Interrupt */
+static void sysevt_received(void *pdata)
+{
+ UNUSED(pdata);
+ /* For now only READY event is received, so we know this is it */
+ __disable_irq();
+ sys_event = true;
+ __enable_irq();
+ /* But later on ... we'll have to parse the answer */
+}
+
+/* returns true if sysevt was already received, which means M0 core is
+ * already up and running */
+static bool sysevt_check(void)
+{
+ /* Check if system is UP and running already */
+ for (unsigned long start = millis(); (millis() - start) < 10;) {
+ /* Wait for 10ms max - if not return an error */
+ if (sys_event) {
+ break;
+ }
+ }
+ if (sys_event) {
+ /* release immediately as M0 already runs */
+ return true;
+ }
+ return false;
+}
+
+static void acl_data_ack(void)
+{
+ /**
+ * The current implementation assumes the taskGUI will not send a new HCI ACL DATA packet before this ack is received
+ * ( which means the CPU2 has handled the previous packet )
+ * In order to implement a secure mechanism, it is required either
+ * - a flow control with the stack
+ * - a local pool of buffer to store packets received from the stack
+ */
+ __disable_irq();
+ acl_data_on = false;
+ __enable_irq();
+}
+
+static bool acl_data_wait(void)
+{
+ /* Wait 10 sec for previous ACL command to be ack'ed by Low Layers
+ * before sending the next one */
+ for (unsigned long start = millis(); (millis() - start) < BLE_IPCC_TIMEOUT;) {
+ /* Wait for 10sec max - if not return an error */
+ if (!acl_data_on) {
+ break;
+ }
+ }
+ if (acl_data_on) {
+ /* no event received, timeout occurs */
+#if defined(PRINT_IPCC_INFO)
+ printf("ERROR: acl data timeout\r\n");
+#endif /*(PRINT_IPCC_INFO)*/
+ return false;
+ }
+ /* release immediately, now that M0 runs */
+ __disable_irq();
+ acl_data_on = false;
+ __enable_irq();
+ return true;
+}
+
+static void syscmd_status_not(SHCI_TL_CmdStatus_t status)
+{
+#if defined(PRINT_IPCC_INFO)
+ printf("syscmd_status_not, status:%d\r\n", status);
+#else
+ UNUSED(status);
+#endif /*(PRINT_IPCC_INFO)*/
+}
+
+/* to received BLE packet from the SharedMem */
+void evt_received(TL_EvtPacket_t *hcievt)
+{
+ uint16_t len = 0;
+
+ /* We need to memcpy the data before passing to higher layers.
+ * The received packet is copied in the _rxbuff
+ * but it must not exceed the BLE_MODULE_SHARED_MEM_BUFFER_SIZE
+ */
+ switch (hcievt->evtserial.type) {
+ case TL_BLEEVT_PKT_TYPE: {
+ /* before starting the running_phase', a RESET command (0x0C03) is sent
+ * by the HCI. Then this evt packet is temporarily kept in the _rxbuff
+ * the set_bd_address (0xFC0C) and the set_tw_power (0xFC0F) commands are sent.
+ * Only when both evt are received (not store in the _rxbuffer),
+ * the Reset packet is handled at HCI layer : the running_phase begins
+ */
+ if (phase_running == false) {
+ /* check the Rx event of complete the previous bd_addr opcode 0xFC0C */
+ if ((hcievt->evtserial.evt.evtcode == TL_BLEEVT_CC_OPCODE) &&
+ (hcievt->evtserial.evt.payload[0] == 0x01) &&
+ (hcievt->evtserial.evt.payload[1] == 0x0C) &&
+ (hcievt->evtserial.evt.payload[2] == 0xFC)) {
+ phase_bd_addr = true;
+ if (hcievt->evtserial.evt.payload[3] != 0) {
+#if defined(PRINT_IPCC_INFO)
+ printf("Error: wrong BD Addr\r\n");
+#endif /*(PRINT_IPCC_INFO)*/
+ }
+ /* rx data is no more useful : not stored in the _rxbuff */
+ break;
+ }
+ /* check the Rx event of complete the previous tx power opcode 0xFC0F */
+ if ((hcievt->evtserial.evt.evtcode == TL_BLEEVT_CC_OPCODE) &&
+ (hcievt->evtserial.evt.payload[0] == 0x01) &&
+ (hcievt->evtserial.evt.payload[1] == 0x0F) &&
+ (hcievt->evtserial.evt.payload[2] == 0xFC)) {
+ phase_tx_power = true;
+ if (hcievt->evtserial.evt.payload[3] != 0) {
+#if defined(PRINT_IPCC_INFO)
+ printf("Error: wrong Tx power\r\n");
+#endif /*(PRINT_IPCC_INFO)*/
+ }
+ /* rx data is no more useful : not stored in the _rxbuff */
+ break;
+ }
+ /* check if the reset phase is in progress (opcode is 0x0C03) */
+ if ((hcievt->evtserial.evt.evtcode == TL_BLEEVT_CC_OPCODE) &&
+ (hcievt->evtserial.evt.payload[0] == 0x01) &&
+ (hcievt->evtserial.evt.payload[1] == 0x03) &&
+ (hcievt->evtserial.evt.payload[2] == 0x0C)) {
+ phase_reset = true;
+#if defined(PRINT_IPCC_INFO)
+ if (hcievt->evtserial.evt.payload[3] != 0) {
+ printf("Error: wrong reset\r\n");
+ }
+#endif /*(PRINT_IPCC_INFO)*/
+ }
+ }
+ __disable_irq();
+ /* store received data in the _rxbuff buffer */
+ len = hcievt->evtserial.evt.plen + TL_EVT_HDR_SIZE;
+ if (len < BLE_MODULE_SHARED_MEM_BUFFER_SIZE - _write_index) {
+ /* at the position of the _write_index */
+ memcpy((uint8_t *)&_rxbuff[_write_index], (uint8_t *)&hcievt->evtserial, len);
+ /* move index */
+ _write_index += len;
+ } else {
+ data_overflow = true;
+ }
+ __enable_irq();
+ }
+ break;
+ case TL_ACL_DATA_PKT_TYPE: {
+ TL_AclDataSerial_t *acl = &(((TL_AclDataPacket_t *)hcievt)->AclDataSerial);
+ __disable_irq();
+ len = acl->length + 5;
+ if (len < BLE_MODULE_SHARED_MEM_BUFFER_SIZE - _write_index) {
+ memcpy((uint8_t *)&_rxbuff[_write_index], (uint8_t *)acl, len);
+ /* move index */
+ _write_index += len;
+ } else {
+ data_overflow = true;
+ }
+ __enable_irq();
+ }
+ break;
+ default:
+ /* should not happen */
+#if defined(PRINT_IPCC_INFO)
+ printf("BLE TL evt_received, wrong type:%d\r\n", hcievt->evtserial.type);
+ while (1); /* let's block to check */
+#endif /*(PRINT_IPCC_INFO)*/
+ break;
+ }
+#if defined(PRINT_IPCC_INFO)
+ if (data_overflow) {
+ printf("Error: data read overflow\r\n");
+ }
+#endif /*(PRINT_IPCC_INFO)*/
+
+ /* In case Event belongs to the Evt Pool we need to inform */
+ if (((uint8_t *)hcievt >= EvtPool) && ((uint8_t *)hcievt < (EvtPool + POOL_SIZE))) {
+ /* Free the message from shared memory */
+ TL_MM_EvtDone(hcievt);
+ }
+}
+
+/* to send BLE packet to the SharedMem */
+uint16_t mbox_write(uint8_t type, uint16_t len, const uint8_t *pData)
+{
+ TL_CmdPacket_t *bleCmdBuf = &BleCmdBuffer;
+ // Note: Until enum is available
+ // type 01 Command
+ // type 02 ACL DATA
+ // type 03 SCO Voice (not supported)
+ // type 04 event - uplink (not supported)
+ switch (type) {
+ case 1: { //BLE command
+ bleCmdBuf->cmdserial.type = type; // for now this param is overwritten in TL_BLE_SendCmd
+ bleCmdBuf->cmdserial.cmd.plen = len;
+ memcpy((void *) &bleCmdBuf->cmdserial.cmd, pData, len);
+ /* We're tracing here the command, after copy in shared mem but before M0 trigger. */
+ TL_BLE_SendCmd(NULL, 0); // unused parameters for now
+ }
+ break;
+ case 2: { //ACL DATA
+ if (!acl_data_wait()) {
+#if defined(PRINT_IPCC_INFO)
+ printf("ERROR: previous ACL message not ACK'd\r\n");
+#endif /*(PRINT_IPCC_INFO)*/
+ /* return number of bytes sent, 0 in this error case */
+ return 0;
+ }
+ TL_AclDataSerial_t *aclDataSerial = (TL_AclDataSerial_t *)(HciAclDataBuffer + sizeof(TL_PacketHeader_t));
+ aclDataSerial->type = type; // for now this param is overwritten in TL_BLE_SendCmd
+ memcpy(HciAclDataBuffer + sizeof(TL_PacketHeader_t) + sizeof(type), pData, len);
+ TL_BLE_SendAclData(NULL, 0); // unused parameters for now
+ __disable_irq();
+ acl_data_on = true; /* data being send */
+ __enable_irq();
+ }
+ break;
+ default:
+#if defined(PRINT_IPCC_INFO)
+ printf("ERROR: not supported type\r\n");
+#endif /*(PRINT_IPCC_INFO)*/
+ /* return number of bytes sent, 0 in this error case */
+ len = 0;
+ break;
+ }
+ return len;
+}
+
+/**
+ * Few utilities functions
+ */
+/* This function fills in a BD address table */
+static bool get_bd_address(uint8_t *bd_addr)
+{
+ uint32_t udn;
+ uint32_t company_id;
+ uint32_t device_id;
+ bool bd_found;
+
+ udn = LL_FLASH_GetUDN();
+
+ if (udn != 0xFFFFFFFF) {
+ /* "Found Unique Device Number: %#06x", udn) */
+
+ company_id = LL_FLASH_GetSTCompanyID();
+ device_id = LL_FLASH_GetDeviceID();
+
+ bd_addr[0] = (uint8_t)(udn & 0x000000FF);
+ bd_addr[1] = (uint8_t)((udn & 0x0000FF00) >> 8);
+ bd_addr[2] = (uint8_t)((udn & 0x00FF0000) >> 16);
+ bd_addr[3] = (uint8_t)device_id;
+ bd_addr[4] = (uint8_t)(company_id & 0x000000FF);
+ bd_addr[5] = (uint8_t)((company_id & 0x0000FF00) >> 8);
+
+ bd_found = true;
+ } else {
+ bd_addr = NULL;
+ bd_found = false;
+ }
+
+ return bd_found;
+}
+
+static void init_debug(void)
+{
+ /* In case of debug profile, configure debugger support */
+
+#if defined(CONFIG_DEBUG)
+#if defined(PRINT_IPCC_INFO)
+ printf("init_debug ENABLED\r\n");
+#endif /*(PRINT_IPCC_INFO)*/
+ /**
+ * Keep debugger enabled while in any low power mode
+ */
+ HAL_DBGMCU_EnableDBGSleepMode();
+ HAL_DBGMCU_EnableDBGStopMode();
+ HAL_DBGMCU_EnableDBGStandbyMode();
+
+ /* Enable debugger: Debug power up request wakeup EXTI line 48 */
+ LL_EXTI_EnableIT_32_63(LL_EXTI_LINE_48);
+ LL_C2_EXTI_EnableIT_32_63(LL_EXTI_LINE_48);
+
+#endif /* CONFIG_DEBUG */
+}
+
+/* Class definition ----------------------------------------------------------*/
+
+HCISharedMemTransportClass::HCISharedMemTransportClass()
+{
+ _read_index = 0; /* fifo position when reading */
+ _write_index = 0; /* fifo position when receiving */
+
+ memset((void *)_rxbuff, 0, sizeof(_rxbuff));
+
+ sys_event = false;
+ acl_data_on = false;
+
+ data_overflow = false;
+
+ phase_bd_addr = false;
+ phase_tx_power = false;
+ phase_reset = false;
+ phase_running = false;
+}
+
+HCISharedMemTransportClass::~HCISharedMemTransportClass()
+{
+}
+
+int HCISharedMemTransportClass::begin()
+{
+ int status = 1;
+ /* clean data Rx variables */
+ _read_index = 0;
+ _write_index = 0;
+
+ memset((void *)_rxbuff, 0, sizeof(_rxbuff));
+
+ /* Check whether M0 sub-system was started already by
+ * checking if the system event was already received
+ * before. If it was not, then go thru all init. */
+ if (!sysevt_check()) {
+ start_ble_rf();
+ init_debug();
+ /* Take BLE out of reset */
+ stm32wb_reset();
+ /* "C2 unlocking" */
+ transport_init();
+ /* At this stage, we got the ready event,
+ * passed thru TL_SYS_EvtReceived */
+
+ WirelessFwInfo_t wireless_info_instance;
+ WirelessFwInfo_t *p_wireless_info = &wireless_info_instance;
+ SHCI_GetWirelessFwInfo(p_wireless_info);
+#if defined(PRINT_IPCC_INFO)
+ printf("WB copro FW version = %d.%d.%d\r\n", p_wireless_info->VersionMajor, p_wireless_info->VersionMinor, p_wireless_info->VersionSub);
+#endif /*(PRINT_IPCC_INFO)*/
+
+ /* Now start BLE service on firmware side, using Vendor specific
+ * command on the System Channel
+ */
+ status = stm32wb_start_ble();
+
+ /* Once reset complete event is received we will need
+ * to send a few more commands:
+ * set bd addr with bt_ipm_set_addr();
+ * during the HCI rest command */
+ }
+ /* IPM Channel is now open */
+#if defined(PRINT_IPCC_INFO)
+ printf("IPM Channel Open Completed\r\n");
+#endif /*(PRINT_IPCC_INFO)*/
+
+ return status;
+}
+
+void HCISharedMemTransportClass::end()
+{
+ /* M0 sub-system is already on (sys_event) */
+ acl_data_on = false;
+ data_overflow = false;
+
+ /* the HCI RESET command ready to be processed again */
+ phase_bd_addr = false;
+ phase_tx_power = false;
+ phase_reset = false;
+ phase_running = false;
+}
+
+void HCISharedMemTransportClass::wait(unsigned long timeout)
+{
+ for (unsigned long start = millis(); (millis() - start) < timeout;) {
+ if (available()) {
+ break;
+ }
+ }
+}
+
+int HCISharedMemTransportClass::available()
+{
+ /* assuming the reset is already achieved,
+ * the LL-only mode is already configured. */
+
+ if (_read_index != _write_index) {
+ return 1;
+ } else if (data_overflow) {
+ __disable_irq();
+ data_overflow = false;
+ __enable_irq();
+ if (_read_index != _write_index) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+int HCISharedMemTransportClass::peek()
+{
+ int peek_val = -1;
+ __disable_irq();
+ if (_read_index != _write_index) {
+ peek_val = _rxbuff[_read_index];
+ }
+ __enable_irq();
+ return peek_val;
+}
+
+int HCISharedMemTransportClass::read()
+{
+ int read_val = -1;
+ __disable_irq();
+ if (_read_index != _write_index) {
+ read_val = _rxbuff[_read_index];
+ _read_index++;
+ if (_read_index == _write_index) {
+ /* Reset buffer index */
+ _read_index = 0;
+ _write_index = 0;
+ }
+ }
+ __enable_irq();
+ return read_val;
+}
+
+size_t HCISharedMemTransportClass::write(const uint8_t *data, size_t length)
+{
+ const uint8_t *msg_data;
+ msg_data = &data[1];
+
+ /* capture the HCI reset send command opcode = 0x0C03
+ * After HCI reset event complete in the evt_received(),
+ * the bd_addr and tx_power must be sent
+ * before the phase_running begins.
+ */
+ if (phase_running) {
+ return mbox_write(data[0], (length - 1), msg_data);;
+ }
+ if ((data[1] == 0x03) && (data[2] == 0x0C)) {
+ phase_reset = false;
+
+ mbox_write(data[0], (length - 1), msg_data);
+
+ /* capture event after HCI_RESET */
+ while (!phase_reset);
+
+ /* set the bd add */
+ if (!bt_ipm_set_addr()) {
+ /* in case of error, no data are written */
+ return 0;
+ }
+ /* wait for the Rx complete */
+ while (!phase_bd_addr);
+ /* this sequence is now complete */
+
+ /* set the Tx power */
+ bt_ipm_set_power();
+ /* wait for the Rx complete */
+ while (!phase_tx_power);
+
+ /* this sequence is now complete */
+ phase_running = true;
+
+ return (length - 1); /* mbox_size of the HCI reset command */
+ }
+ return 0; /* mbox_size of the HCI reset command */
+}
+
+//private:
+void HCISharedMemTransportClass::start_ble_rf(void)
+{
+ if ((LL_RCC_IsActiveFlag_PINRST()) && (!LL_RCC_IsActiveFlag_SFTRST())) {
+ /* Simulate power off reset */
+ LL_PWR_EnableBkUpAccess();
+ LL_PWR_EnableBkUpAccess();
+ LL_RCC_ForceBackupDomainReset();
+ LL_RCC_ReleaseBackupDomainReset();
+ }
+
+ /* Switch OFF LSI as LSE is the source clock */
+ LL_RCC_LSI2_Disable();
+}
+
+void HCISharedMemTransportClass::stm32wb_reset(void)
+{
+ // Reset IPCC
+ LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_IPCC);
+
+ LL_C1_IPCC_ClearFlag_CHx(
+ IPCC,
+ LL_IPCC_CHANNEL_1 | LL_IPCC_CHANNEL_2 | LL_IPCC_CHANNEL_3 | LL_IPCC_CHANNEL_4
+ | LL_IPCC_CHANNEL_5 | LL_IPCC_CHANNEL_6);
+
+ LL_C2_IPCC_ClearFlag_CHx(
+ IPCC,
+ LL_IPCC_CHANNEL_1 | LL_IPCC_CHANNEL_2 | LL_IPCC_CHANNEL_3 | LL_IPCC_CHANNEL_4
+ | LL_IPCC_CHANNEL_5 | LL_IPCC_CHANNEL_6);
+
+ LL_C1_IPCC_DisableTransmitChannel(
+ IPCC,
+ LL_IPCC_CHANNEL_1 | LL_IPCC_CHANNEL_2 | LL_IPCC_CHANNEL_3 | LL_IPCC_CHANNEL_4
+ | LL_IPCC_CHANNEL_5 | LL_IPCC_CHANNEL_6);
+
+ LL_C2_IPCC_DisableTransmitChannel(
+ IPCC,
+ LL_IPCC_CHANNEL_1 | LL_IPCC_CHANNEL_2 | LL_IPCC_CHANNEL_3 | LL_IPCC_CHANNEL_4
+ | LL_IPCC_CHANNEL_5 | LL_IPCC_CHANNEL_6);
+
+ LL_C1_IPCC_DisableReceiveChannel(
+ IPCC,
+ LL_IPCC_CHANNEL_1 | LL_IPCC_CHANNEL_2 | LL_IPCC_CHANNEL_3 | LL_IPCC_CHANNEL_4
+ | LL_IPCC_CHANNEL_5 | LL_IPCC_CHANNEL_6);
+
+ LL_C2_IPCC_DisableReceiveChannel(
+ IPCC,
+ LL_IPCC_CHANNEL_1 | LL_IPCC_CHANNEL_2 | LL_IPCC_CHANNEL_3 | LL_IPCC_CHANNEL_4
+ | LL_IPCC_CHANNEL_5 | LL_IPCC_CHANNEL_6);
+
+ /* IPCC default IRQ handlers: IPCC_C1_TX_IRQHandler & IPCC_C1_RX_IRQHandler
+ * are mapped in the flash mem area, so that NVIC does not need to SetVector
+ */
+}
+
+int HCISharedMemTransportClass::stm32wb_start_ble(void)
+{
+ SHCI_C2_Ble_Init_Cmd_Packet_t ble_init_cmd_packet = {
+ 0, 0, 0, /**< Header unused */
+ 0, /** pBleBufferAddress not used */
+ 0, /** BleBufferSize not used */
+ CFG_BLE_NUM_GATT_ATTRIBUTES,
+ CFG_BLE_NUM_GATT_SERVICES,
+ CFG_BLE_ATT_VALUE_ARRAY_SIZE,
+ CFG_BLE_NUM_LINK,
+ CFG_BLE_DATA_LENGTH_EXTENSION,
+ CFG_BLE_PREPARE_WRITE_LIST_SIZE,
+ CFG_BLE_MBLOCK_COUNT,
+ CFG_BLE_MAX_ATT_MTU,
+ CFG_BLE_SLAVE_SCA,
+ CFG_BLE_MASTER_SCA,
+ CFG_BLE_LSE_SOURCE,
+ CFG_BLE_MAX_CONN_EVENT_LENGTH,
+ CFG_BLE_HSE_STARTUP_TIME,
+ CFG_BLE_VITERBI_MODE,
+ CFG_BLE_LL_ONLY,
+ 0 /** TODO Should be read from HW */
+ };
+ /**
+ * Starts the BLE Stack on CPU2
+ */
+ if (SHCI_C2_BLE_Init(&ble_init_cmd_packet) == SHCI_Success) {
+ return 1;
+ }
+ return 0;
+}
+
+void HCISharedMemTransportClass::transport_init(void)
+{
+ TL_MM_Config_t tl_mm_config;
+ TL_BLE_InitConf_t tl_ble_config;
+ /* STM32WB offers a System Channel HCI interface for
+ offering system services, with proprietary commands.
+ System Channel must be used as well for starting up
+ BLE service so we need to initialize it. */
+ SHCI_TL_HciInitConf_t shci_init_config;
+
+ /**< Reference table initialization */
+ TL_Init();
+
+ /**< System channel initialization */
+ shci_init_config.p_cmdbuffer = (uint8_t *)&SystemCmdBuffer;
+ shci_init_config.StatusNotCallBack = syscmd_status_not;
+ shci_init(sysevt_received, (void *) &shci_init_config);
+
+ /**< Memory Manager channel initialization */
+ tl_mm_config.p_BleSpareEvtBuffer = BleSpareEvtBuffer;
+ tl_mm_config.p_SystemSpareEvtBuffer = SystemSpareEvtBuffer;
+ tl_mm_config.p_AsynchEvtPool = EvtPool;
+ tl_mm_config.AsynchEvtPoolSize = POOL_SIZE;
+ TL_MM_Init(&tl_mm_config);
+
+ TL_Enable();
+
+ /* At this stage, we'll need to wait for ready event,
+ * passed thru TL_SYS_EvtReceived */
+ if (!sysevt_wait()) {
+#if defined(PRINT_IPCC_INFO)
+ printf("ERROR booting WB controller\r\n");
+#endif /*(PRINT_IPCC_INFO)*/
+ } else {
+ /**< BLE channel initialization */
+ tl_ble_config.p_cmdbuffer = (uint8_t *)&BleCmdBuffer;
+ tl_ble_config.p_AclDataBuffer = HciAclDataBuffer;
+ tl_ble_config.IoBusEvtCallBack = evt_received;
+ tl_ble_config.IoBusAclDataTxAck = acl_data_ack;
+ TL_BLE_Init((void *)&tl_ble_config);
+ }
+}
+
+int HCISharedMemTransportClass::bt_ipm_set_addr(void)
+{
+ /* the specific table for set addr is 8 bytes:
+ * one byte for config_offset
+ * one byte for length
+ * 6 bytes for payload */
+ uint8_t data[4 + 8];
+
+ phase_bd_addr = false;
+
+ if (get_bd_address(bd_addr_udn)) {
+ /* create ACI_HAL_WRITE_CONFIG_DATA */
+
+ data[0] = BT_BUF_CMD;
+ data[1] = uint8_t(ACI_WRITE_CONFIG_DATA_OPCODE & 0x000000FF); /* OCF */
+ data[2] = uint8_t((ACI_WRITE_CONFIG_DATA_OPCODE & 0x0000FF00) >> 8); /* OGF */
+ data[3] = 8; /* length of parameters */
+ /* fill the ACI_HAL_WRITE_CONFIG_DATA with the addr*/
+ data[4] = CONFIG_DATA_PUBADDR_OFFSET; /* the offset */
+ data[5] = 6; /* is the length of the bd_addr table */
+ memcpy(data + 6, bd_addr_udn, 6);
+ /* send the ACI_HAL_WRITE_CONFIG_DATA */
+ mbox_write(data[0], 11, &data[1]);
+ /* now wait for the corresponding Rx event */
+ return 1; /* success */
+ }
+ return 0; /* Error */
+}
+
+int HCISharedMemTransportClass::bt_ipm_set_power(void)
+{
+ /* the specific table for power is 2 bytes:
+ * En_High_Power byte, PA_level byte */
+ uint8_t data[4 + 2];
+
+ phase_tx_power = false;
+
+ data[0] = BT_BUF_CMD; /* the type */
+ data[1] = (uint8_t)(ACI_HAL_SET_TX_POWER_LEVEL & 0x000000FF); /* the OPCODE */
+ data[2] = (uint8_t)((ACI_HAL_SET_TX_POWER_LEVEL & 0x0000FF00) >> 8);
+ data[3] = 2; /* the length */
+ /* fill the ACI_HAL_WRITE_CONFIG_DATA */
+ data[4] = 0x01; /* En_High_Power */
+ data[5] = CFG_TX_POWER; /* PA_level */
+
+ /* send the ACI_HAL_WRITE_CONFIG_DATA */
+ mbox_write(data[0], 5, &data[1]);
+ /* now wait for the corresponding Rx event */
+ return 1; /* success */
+}
+
+#endif /* STM32WBxx */
diff --git a/src/utility/HCISharedMemTransport.h b/src/utility/HCISharedMemTransport.h
new file mode 100644
index 00000000..9b9751f2
--- /dev/null
+++ b/src/utility/HCISharedMemTransport.h
@@ -0,0 +1,94 @@
+/*
+ This file is part of the STM32duinoBLE library.
+ Copyright (c) 2019 STMicroelectronics. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef _HCI_SHARED_MEM_TRANSPORT_H_
+#define _HCI_SHARED_MEM_TRANSPORT_H_
+
+#include "HCITransport.h"
+
+/* STM32WB include files */
+#include "stm32wb55xx.h"
+#include "stm32wbxx_ll_rcc.h"
+#include "stm32wbxx_ll_ipcc.h"
+#include "stm32wbxx_ll_system.h"
+#include "STM32Cube_FW/tl.h"
+#include "STM32Cube_FW/shci.h"
+#include "STM32Cube_FW/shci_tl.h"
+#include "STM32Cube_FW/app_conf.h"
+
+/* this one is for printing info content when HW serial enabled */
+//#define PRINT_IPCC_INFO
+
+/* this CONFIG_DEBUG must be defined for -Og option */
+//#define CONFIG_DEBUG
+
+/******************************************************************************
+ * BLE config parameters
+ ******************************************************************************/
+/* Defined from WB Cube reference SW */
+#define CFG_TLBLE_EVT_QUEUE_LENGTH 5
+#define CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE 255 /**< Set to 255 with the memory manager and the mailbox */
+#define TL_BLE_EVENT_FRAME_SIZE ( TL_EVT_HDR_SIZE + CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE )
+#define POOL_SIZE (CFG_TLBLE_EVT_QUEUE_LENGTH*4*DIVC(( sizeof(TL_PacketHeader_t) + TL_BLE_EVENT_FRAME_SIZE ), 4))
+
+#define CONFIG_DATA_PUBADDR_OFFSET (0x00) /**< Bluetooth public address */
+#define CONFIG_DATA_PUBADDR_LEN (6)
+
+#define BT_BUF_CMD 1
+#define BT_BUF_ACL_OUT 2
+
+/* timeout (in ms) to wait for an incoming event */
+#define BLE_IPCC_TIMEOUT 10000
+
+/* to received BLE packet from the SharedMem */
+void evt_received(TL_EvtPacket_t *hcievt);
+
+/* to send BLE packet to the SharedMem */
+uint16_t mbox_write(uint8_t type, uint16_t len, const uint8_t *pData);
+
+class HCISharedMemTransportClass : public HCITransportInterface {
+ public:
+ HCISharedMemTransportClass();
+ virtual ~HCISharedMemTransportClass();
+
+ virtual int begin();
+ virtual void end();
+
+ virtual void wait(unsigned long timeout);
+
+ virtual int available();
+ virtual int peek();
+ virtual int read();
+
+ virtual size_t write(const uint8_t *data, size_t length);
+
+ private:
+
+ /* method to initialize the BLE device */
+ void transport_init(void);
+ void start_ble_rf(void);
+ void stm32wb_reset(void);
+ int stm32wb_start_ble(void);
+ int bt_ipm_ble_init(void);
+ int bt_ipm_set_addr(void);
+ int bt_ipm_set_power(void);
+
+};
+
+#endif /* _HCI_SHARED_MEM_TRANSPORT_H_ */
diff --git a/src/utility/HCISpiTransport.cpp b/src/utility/HCISpiTransport.cpp
index 99dd6ca2..512e6e9a 100644
--- a/src/utility/HCISpiTransport.cpp
+++ b/src/utility/HCISpiTransport.cpp
@@ -21,7 +21,7 @@
volatile int data_avail = 0;
-HCISpiTransportClass::HCISpiTransportClass(SPIClass& spi, BLEChip_t ble_chip, uint8_t cs_pin, uint8_t spi_irq, uint8_t ble_rst, uint32_t frequency, uint8_t spi_mode) :
+HCISpiTransportClass::HCISpiTransportClass(SPIClass &spi, BLEChip_t ble_chip, uint8_t cs_pin, uint8_t spi_irq, uint8_t ble_rst, uint32_t frequency, uint8_t spi_mode) :
_spi(&spi),
_ble_chip(ble_chip),
_cs_pin(cs_pin),
@@ -66,16 +66,13 @@ int HCISpiTransportClass::begin()
digitalWrite(_ble_rst, HIGH);
delay(5);
- if (_ble_chip == SPBTLE_RF || _ble_chip == BLUENRG_M0)
- {
+ if (_ble_chip == SPBTLE_RF || _ble_chip == BLUENRG_M0) {
// Wait for Blue Initialize
wait_for_blue_initialize();
- } else if (_ble_chip == SPBTLE_1S || _ble_chip == BLUENRG_M2SP)
- {
+ } else if (_ble_chip == SPBTLE_1S || _ble_chip == BLUENRG_M2SP) {
// Wait a while for the reset of the BLE module
delay(300);
- } else
- {
+ } else {
// BLE chip not supported
return 0;
}
@@ -91,10 +88,8 @@ void HCISpiTransportClass::end()
void HCISpiTransportClass::wait(unsigned long timeout)
{
- for (unsigned long start = millis(); (millis() - start) < timeout;)
- {
- if (available())
- {
+ for (unsigned long start = millis(); (millis() - start) < timeout;) {
+ if (available()) {
break;
}
}
@@ -102,31 +97,25 @@ void HCISpiTransportClass::wait(unsigned long timeout)
int HCISpiTransportClass::available()
{
- if(_ble_chip != SPBTLE_RF && _ble_chip != SPBTLE_1S && _ble_chip != BLUENRG_M2SP && _ble_chip != BLUENRG_M0)
- {
+ if (_ble_chip != SPBTLE_RF && _ble_chip != SPBTLE_1S && _ble_chip != BLUENRG_M2SP && _ble_chip != BLUENRG_M0) {
return 0;
}
- if(_read_index != _write_index)
- {
+ if (_read_index != _write_index) {
return 1;
- } else if(data_avail)
- {
+ } else if (data_avail) {
int ble_reset = 0;
- if(digitalRead(_spi_irq) == 0)
- {
+ if (digitalRead(_spi_irq) == 0) {
return 0;
}
data_avail = 0;
- while(digitalRead(_spi_irq) == 1 && _write_index != BLE_MODULE_SPI_BUFFER_SIZE)
- {
+ while (digitalRead(_spi_irq) == 1 && _write_index != BLE_MODULE_SPI_BUFFER_SIZE) {
uint8_t header_master[5] = {0x0b, 0x00, 0x00, 0x00, 0x00};
- if(_ble_chip == SPBTLE_1S || _ble_chip == BLUENRG_M2SP)
- {
+ if (_ble_chip == SPBTLE_1S || _ble_chip == BLUENRG_M2SP) {
detachInterrupt(_spi_irq);
}
@@ -137,112 +126,91 @@ int HCISpiTransportClass::available()
/* Write the header */
_spi->transfer(header_master, 5);
- if (_ble_chip == SPBTLE_RF || _ble_chip == BLUENRG_M0)
- {
+ if (_ble_chip == SPBTLE_RF || _ble_chip == BLUENRG_M0) {
/* device is ready */
- if(header_master[0] == 0x02)
- {
+ if (header_master[0] == 0x02) {
uint16_t byte_count = (header_master[4] << 8) | header_master[3];
- if(byte_count > 0)
- {
- if(_initial_phase)
- {
+ if (byte_count > 0) {
+ if (_initial_phase) {
/* avoid to read more data that available size of the buffer */
- if(byte_count > (BLE_MODULE_SPI_BUFFER_SIZE - _write_index_initial))
- {
+ if (byte_count > (BLE_MODULE_SPI_BUFFER_SIZE - _write_index_initial)) {
byte_count = (BLE_MODULE_SPI_BUFFER_SIZE - _write_index_initial);
}
/* Read the response */
- for(int j=0; j < byte_count; j++)
- {
+ for (int j = 0; j < byte_count; j++) {
_rxbuff[_write_index_initial] = _spi->transfer(0xFF);
_write_index_initial++;
}
/* Check if the message is a Blue Initialize */
/* If so we need to send the command to enable LL_ONLY */
- if(byte_count == 6)
- {
- if(_rxbuff[_write_index_initial - 6] == 0x04 &&
- _rxbuff[_write_index_initial - 5] == 0xFF &&
- _rxbuff[_write_index_initial - 4] == 0x03 &&
- _rxbuff[_write_index_initial - 3] == 0x01 &&
- _rxbuff[_write_index_initial - 2] == 0x00 &&
- _rxbuff[_write_index_initial - 1] == 0x01)
- {
+ if (byte_count == 6) {
+ if (_rxbuff[_write_index_initial - 6] == 0x04 &&
+ _rxbuff[_write_index_initial - 5] == 0xFF &&
+ _rxbuff[_write_index_initial - 4] == 0x03 &&
+ _rxbuff[_write_index_initial - 3] == 0x01 &&
+ _rxbuff[_write_index_initial - 2] == 0x00 &&
+ _rxbuff[_write_index_initial - 1] == 0x01) {
ble_reset = 1;
}
}
- } else
- {
+ } else {
/* avoid to read more data that available size of the buffer */
- if(byte_count > (BLE_MODULE_SPI_BUFFER_SIZE - _write_index))
- {
+ if (byte_count > (BLE_MODULE_SPI_BUFFER_SIZE - _write_index)) {
byte_count = (BLE_MODULE_SPI_BUFFER_SIZE - _write_index);
/* SPI buffer is full but we still have data to store, so we set the data_avail flag to true */
data_avail = 1;
}
/* Read the response */
- for(int j=0; j < byte_count; j++)
- {
+ for (int j = 0; j < byte_count; j++) {
_rxbuff[_write_index] = _spi->transfer(0xFF);
_write_index++;
}
}
}
}
- } else if (_ble_chip == SPBTLE_1S || _ble_chip == BLUENRG_M2SP)
- {
+ } else if (_ble_chip == SPBTLE_1S || _ble_chip == BLUENRG_M2SP) {
uint16_t byte_count = (header_master[4] << 8) | header_master[3];
- if(byte_count > 0)
- {
- if(_initial_phase)
- {
+ if (byte_count > 0) {
+ if (_initial_phase) {
/* avoid to read more data that available size of the buffer */
- if(byte_count > (BLE_MODULE_SPI_BUFFER_SIZE - _write_index_initial))
- {
+ if (byte_count > (BLE_MODULE_SPI_BUFFER_SIZE - _write_index_initial)) {
byte_count = (BLE_MODULE_SPI_BUFFER_SIZE - _write_index_initial);
}
/* Read the response */
- for(int j=0; j < byte_count; j++)
- {
+ for (int j = 0; j < byte_count; j++) {
_rxbuff[_write_index_initial] = _spi->transfer(0xFF);
_write_index_initial++;
}
/* Check if the message is a CMD_COMPLETE */
/* We suppose that the first CMD is always a HCI_RESET */
- if(byte_count == 7)
- {
- if(_rxbuff[_write_index_initial - 7] == 0x04 &&
- _rxbuff[_write_index_initial - 6] == 0x0E &&
- _rxbuff[_write_index_initial - 5] == 0x04 &&
- _rxbuff[_write_index_initial - 4] == 0x01 &&
- _rxbuff[_write_index_initial - 3] == 0x03 &&
- _rxbuff[_write_index_initial - 2] == 0x0C &&
- _rxbuff[_write_index_initial - 1] == 0x00)
- {
+ if (byte_count == 7) {
+ if (_rxbuff[_write_index_initial - 7] == 0x04 &&
+ _rxbuff[_write_index_initial - 6] == 0x0E &&
+ _rxbuff[_write_index_initial - 5] == 0x04 &&
+ _rxbuff[_write_index_initial - 4] == 0x01 &&
+ _rxbuff[_write_index_initial - 3] == 0x03 &&
+ _rxbuff[_write_index_initial - 2] == 0x0C &&
+ _rxbuff[_write_index_initial - 1] == 0x00) {
ble_reset = 1;
}
}
- } else
- {
+ } else {
/* avoid to read more data that available size of the buffer */
- if(byte_count > (BLE_MODULE_SPI_BUFFER_SIZE - _write_index))
- {
+ if (byte_count > (BLE_MODULE_SPI_BUFFER_SIZE - _write_index)) {
byte_count = (BLE_MODULE_SPI_BUFFER_SIZE - _write_index);
/* SPI buffer is full but we still have data to store, so we set the data_avail flag to true */
data_avail = 1;
}
/* Read the response */
- for(int j=0; j < byte_count; j++)
- {
+ for (int j = 0; j < byte_count; j++) {
_rxbuff[_write_index] = _spi->transfer(0xFF);
_write_index++;
}
@@ -254,21 +222,17 @@ int HCISpiTransportClass::available()
_spi->endTransaction();
- if(_ble_chip == SPBTLE_1S || _ble_chip == BLUENRG_M2SP)
- {
+ if (_ble_chip == SPBTLE_1S || _ble_chip == BLUENRG_M2SP) {
attachInterrupt(_spi_irq, SPI_Irq_Callback, RISING);
}
}
- if(ble_reset)
- {
- if (_ble_chip == SPBTLE_RF || _ble_chip == BLUENRG_M0)
- {
+ if (ble_reset) {
+ if (_ble_chip == SPBTLE_RF || _ble_chip == BLUENRG_M0) {
/* BLE chip was reset: we need to enable LL_ONLY */
enable_ll_only();
wait_for_enable_ll_only();
- } else if (_ble_chip == SPBTLE_1S || _ble_chip == BLUENRG_M2SP)
- {
+ } else if (_ble_chip == SPBTLE_1S || _ble_chip == BLUENRG_M2SP) {
/* BLE chip was reset: we need to wait for a while */
delay(300);
}
@@ -279,15 +243,12 @@ int HCISpiTransportClass::available()
_write_index_initial = 0;
}
- if(_read_index != _write_index)
- {
+ if (_read_index != _write_index) {
return 1;
- } else
- {
+ } else {
return 0;
}
- } else
- {
+ } else {
return 0;
}
}
@@ -296,8 +257,7 @@ int HCISpiTransportClass::peek()
{
int peek_val = -1;
- if(_read_index != _write_index)
- {
+ if (_read_index != _write_index) {
peek_val = _rxbuff[_read_index];
}
@@ -308,12 +268,10 @@ int HCISpiTransportClass::read()
{
int read_val = -1;
- if(_read_index != _write_index)
- {
+ if (_read_index != _write_index) {
read_val = _rxbuff[_read_index];
_read_index++;
- if(_read_index == _write_index)
- {
+ if (_read_index == _write_index) {
/* Reset buffer index */
_read_index = 0;
_write_index = 0;
@@ -323,22 +281,19 @@ int HCISpiTransportClass::read()
return read_val;
}
-size_t HCISpiTransportClass::write(const uint8_t* data, size_t length)
+size_t HCISpiTransportClass::write(const uint8_t *data, size_t length)
{
uint8_t header_master[5] = {0x0a, 0x00, 0x00, 0x00, 0x00};
void *my_data = (void *)data;
int result = 0;
uint32_t tickstart = millis();
- if(_ble_chip != SPBTLE_RF && _ble_chip != SPBTLE_1S && _ble_chip != BLUENRG_M2SP && _ble_chip != BLUENRG_M0)
- {
+ if (_ble_chip != SPBTLE_RF && _ble_chip != SPBTLE_1S && _ble_chip != BLUENRG_M2SP && _ble_chip != BLUENRG_M0) {
return 0;
}
- do
- {
- if (_ble_chip == SPBTLE_RF || _ble_chip == BLUENRG_M0)
- {
+ do {
+ if (_ble_chip == SPBTLE_RF || _ble_chip == BLUENRG_M0) {
result = 0;
_spi->beginTransaction(_spiSettings);
@@ -349,18 +304,14 @@ size_t HCISpiTransportClass::write(const uint8_t* data, size_t length)
_spi->transfer(header_master, 5);
/* device is ready */
- if(header_master[0] == 0x02)
- {
- if(header_master[1] >= length)
- {
+ if (header_master[0] == 0x02) {
+ if (header_master[1] >= length) {
/* Write the data */
_spi->transfer(my_data, length);
- } else
- {
+ } else {
result = -2;
}
- } else
- {
+ } else {
result = -1;
}
@@ -368,13 +319,11 @@ size_t HCISpiTransportClass::write(const uint8_t* data, size_t length)
_spi->endTransaction();
- if((millis() - tickstart) > 1000)
- {
+ if ((millis() - tickstart) > 1000) {
result = -3;
break;
}
- } else if (_ble_chip == SPBTLE_1S || _ble_chip == BLUENRG_M2SP)
- {
+ } else if (_ble_chip == SPBTLE_1S || _ble_chip == BLUENRG_M2SP) {
uint32_t tickstart_data_available = millis();
result = 0;
@@ -388,17 +337,14 @@ size_t HCISpiTransportClass::write(const uint8_t* data, size_t length)
* Wait until BlueNRG-1 is ready.
* When ready it will raise the IRQ pin.
*/
- while(!(digitalRead(_spi_irq) == 1))
- {
- if((millis() - tickstart_data_available) > 1000)
- {
+ while (!(digitalRead(_spi_irq) == 1)) {
+ if ((millis() - tickstart_data_available) > 1000) {
result = -3;
break;
}
}
- if(result == -3)
- {
+ if (result == -3) {
digitalWrite(_cs_pin, HIGH);
_spi->endTransaction();
attachInterrupt(_spi_irq, SPI_Irq_Callback, RISING);
@@ -408,12 +354,10 @@ size_t HCISpiTransportClass::write(const uint8_t* data, size_t length)
/* Write the header */
_spi->transfer(header_master, 5);
- if((int)((((uint16_t)header_master[2])<<8) | ((uint16_t)header_master[1])) >= (int)length)
- {
+ if ((int)((((uint16_t)header_master[2]) << 8) | ((uint16_t)header_master[1])) >= (int)length) {
/* Write the data */
_spi->transfer(my_data, length);
- } else
- {
+ } else {
result = -2;
}
@@ -423,19 +367,16 @@ size_t HCISpiTransportClass::write(const uint8_t* data, size_t length)
attachInterrupt(_spi_irq, SPI_Irq_Callback, RISING);
- if((millis() - tickstart) > 1000)
- {
+ if ((millis() - tickstart) > 1000) {
result = -3;
break;
}
}
- } while(result < 0);
+ } while (result < 0);
- if(result < 0)
- {
+ if (result < 0) {
return 0;
- } else
- {
+ } else {
return length;
}
}
@@ -445,18 +386,15 @@ void HCISpiTransportClass::wait_for_blue_initialize()
int event_blue_initialize = 0;
uint8_t event[16];
- do
- {
- while(!data_avail);
+ do {
+ while (!data_avail);
- if(digitalRead(_spi_irq) == 0)
- {
+ if (digitalRead(_spi_irq) == 0) {
continue;
}
data_avail = 0;
- while(digitalRead(_spi_irq) == 1)
- {
+ while (digitalRead(_spi_irq) == 1) {
uint8_t header_master[5] = {0x0b, 0x00, 0x00, 0x00, 0x00};
_spi->beginTransaction(_spiSettings);
@@ -467,34 +405,27 @@ void HCISpiTransportClass::wait_for_blue_initialize()
_spi->transfer(header_master, 5);
/* device is ready */
- if(header_master[0] == 0x02)
- {
+ if (header_master[0] == 0x02) {
/* device is ready */
uint16_t byte_count = (header_master[4] << 8) | header_master[3];
- if(byte_count > 0)
- {
+ if (byte_count > 0) {
/* Read the response */
- if(byte_count == 6)
- {
- for(int j=0; j < byte_count; j++)
- {
+ if (byte_count == 6) {
+ for (int j = 0; j < byte_count; j++) {
event[j] = _spi->transfer(0xFF);
}
- if(event[0] == 0x04 &&
- event[1] == 0xFF &&
- event[2] == 0x03 &&
- event[3] == 0x01 &&
- event[4] == 0x00 &&
- event[5] == 0x01)
- {
+ if (event[0] == 0x04 &&
+ event[1] == 0xFF &&
+ event[2] == 0x03 &&
+ event[3] == 0x01 &&
+ event[4] == 0x00 &&
+ event[5] == 0x01) {
event_blue_initialize = 1;
}
- } else
- {
- for(int j=0; j < byte_count; j++)
- {
+ } else {
+ for (int j = 0; j < byte_count; j++) {
_spi->transfer(0xFF);
}
}
@@ -505,7 +436,7 @@ void HCISpiTransportClass::wait_for_blue_initialize()
_spi->endTransaction();
}
- } while(!event_blue_initialize);
+ } while (!event_blue_initialize);
}
void HCISpiTransportClass::wait_for_enable_ll_only()
@@ -513,18 +444,15 @@ void HCISpiTransportClass::wait_for_enable_ll_only()
uint8_t data[8];
int status = 0;
- do
- {
- while(!data_avail);
+ do {
+ while (!data_avail);
- if(digitalRead(_spi_irq) == 0)
- {
+ if (digitalRead(_spi_irq) == 0) {
continue;
}
data_avail = 0;
- while(digitalRead(_spi_irq) == 1)
- {
+ while (digitalRead(_spi_irq) == 1) {
uint8_t header_master[5] = {0x0b, 0x00, 0x00, 0x00, 0x00};
_spi->beginTransaction(_spiSettings);
@@ -535,29 +463,24 @@ void HCISpiTransportClass::wait_for_enable_ll_only()
_spi->transfer(header_master, 5);
/* device is ready */
- if(header_master[0] == 0x02)
- {
+ if (header_master[0] == 0x02) {
/* device is ready */
uint16_t byte_count = (header_master[4] << 8) | header_master[3];
- if(byte_count > 0)
- {
+ if (byte_count > 0) {
/* Read the response */
- for(int j=0; j < byte_count; j++)
- {
+ for (int j = 0; j < byte_count; j++) {
data[j] = _spi->transfer(0xFF);
}
- if(byte_count == 7)
- {
- if(data[0] == 0x04 &&
- data[1] == 0x0E &&
- data[2] == 0x04 &&
- data[3] == 0x01 &&
- data[4] == 0x0C &&
- data[5] == 0xFC &&
- data[6] == 0x00)
- {
+ if (byte_count == 7) {
+ if (data[0] == 0x04 &&
+ data[1] == 0x0E &&
+ data[2] == 0x04 &&
+ data[3] == 0x01 &&
+ data[4] == 0x0C &&
+ data[5] == 0xFC &&
+ data[6] == 0x00) {
status = 1;
}
}
@@ -568,17 +491,16 @@ void HCISpiTransportClass::wait_for_enable_ll_only()
_spi->endTransaction();
}
- } while(!status);
+ } while (!status);
}
void HCISpiTransportClass::enable_ll_only()
{
uint8_t header_master[5] = {0x0a, 0x00, 0x00, 0x00, 0x00};
- uint8_t cmd[7] = {0x01,0x0C,0xFC,0x03,0x2C,0x01,0x01}; // Enable LL_ONLY
+ uint8_t cmd[7] = {0x01, 0x0C, 0xFC, 0x03, 0x2C, 0x01, 0x01}; // Enable LL_ONLY
int result = 0;
- do
- {
+ do {
result = 0;
_spi->beginTransaction(_spiSettings);
@@ -589,19 +511,15 @@ void HCISpiTransportClass::enable_ll_only()
_spi->transfer(header_master, 5);
/* device is ready */
- if(header_master[0] == 0x02)
- {
+ if (header_master[0] == 0x02) {
/* Write the data */
- if(header_master[1] >= 7)
- {
+ if (header_master[1] >= 7) {
/* Write the data */
_spi->transfer((void *)cmd, 7);
- } else
- {
+ } else {
result = -2;
}
- } else
- {
+ } else {
result = -1;
}
diff --git a/src/utility/HCISpiTransport.h b/src/utility/HCISpiTransport.h
index e16502f1..4da3befb 100644
--- a/src/utility/HCISpiTransport.h
+++ b/src/utility/HCISpiTransport.h
@@ -31,41 +31,41 @@ typedef enum BLEChip_s {
} BLEChip_t;
#ifndef BLE_SPI_BYTE_ORDER
-#define BLE_SPI_BYTE_ORDER MSBFIRST
+ #define BLE_SPI_BYTE_ORDER MSBFIRST
#endif
#define BLE_MODULE_SPI_BUFFER_SIZE 128
class HCISpiTransportClass : public HCITransportInterface {
-public:
- HCISpiTransportClass(SPIClass& spi, BLEChip_t ble_chip, uint8_t cs_pin, uint8_t spi_irq, uint8_t ble_rst, uint32_t frequency, uint8_t spi_mode);
- virtual ~HCISpiTransportClass();
+ public:
+ HCISpiTransportClass(SPIClass &spi, BLEChip_t ble_chip, uint8_t cs_pin, uint8_t spi_irq, uint8_t ble_rst, uint32_t frequency, uint8_t spi_mode);
+ virtual ~HCISpiTransportClass();
- virtual int begin();
- virtual void end();
+ virtual int begin();
+ virtual void end();
- virtual void wait(unsigned long timeout);
+ virtual void wait(unsigned long timeout);
- virtual int available();
- virtual int peek();
- virtual int read();
+ virtual int available();
+ virtual int peek();
+ virtual int read();
- virtual size_t write(const uint8_t* data, size_t length);
+ virtual size_t write(const uint8_t *data, size_t length);
-private:
- void wait_for_blue_initialize();
- void wait_for_enable_ll_only();
- void enable_ll_only();
- SPIClass* _spi;
- SPISettings _spiSettings;
- BLEChip_t _ble_chip;
- uint8_t _cs_pin;
- uint8_t _spi_irq;
- uint8_t _ble_rst;
- uint8_t _rxbuff[BLE_MODULE_SPI_BUFFER_SIZE];
- uint16_t _read_index;
- uint16_t _write_index;
- uint16_t _write_index_initial;
- uint8_t _initial_phase;
+ private:
+ void wait_for_blue_initialize();
+ void wait_for_enable_ll_only();
+ void enable_ll_only();
+ SPIClass *_spi;
+ SPISettings _spiSettings;
+ BLEChip_t _ble_chip;
+ uint8_t _cs_pin;
+ uint8_t _spi_irq;
+ uint8_t _ble_rst;
+ uint8_t _rxbuff[BLE_MODULE_SPI_BUFFER_SIZE];
+ uint16_t _read_index;
+ uint16_t _write_index;
+ uint16_t _write_index_initial;
+ uint8_t _initial_phase;
};
#endif /* _HCI_SPI_TRANSPORT_H_ */
diff --git a/src/utility/STM32Cube_FW/README.md b/src/utility/STM32Cube_FW/README.md
new file mode 100644
index 00000000..880fcbbc
--- /dev/null
+++ b/src/utility/STM32Cube_FW/README.md
@@ -0,0 +1,6 @@
+
+## Source
+
+[STMicroelectronics/STM32CubeWB Release v1.8.0](https://github.com/STMicroelectronics/STM32CubeWB/releases/tag/v1.8.0)
+- Application: [BLE_TransparentMode](https://github.com/STMicroelectronics/STM32CubeWB/tree/v1.8.0/Projects/P-NUCLEO-WB55.Nucleo/Applications/BLE/BLE_TransparentMode)
+
diff --git a/src/utility/STM32Cube_FW/app_conf.h b/src/utility/STM32Cube_FW/app_conf.h
new file mode 100644
index 00000000..667dbbd4
--- /dev/null
+++ b/src/utility/STM32Cube_FW/app_conf.h
@@ -0,0 +1,158 @@
+/**
+ ******************************************************************************
+ * File Name : app_conf.h
+ * Description : Application configuration file for STM32WPAN Middleware.
+ ******************************************************************************
+ * @attention
+ *
+ *
© Copyright (c) 2020 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software component is licensed by ST under Ultimate Liberty license
+ * SLA0044, the "License"; You may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at:
+ * www.st.com/SLA0044
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef APP_CONF_H
+#define APP_CONF_H
+
+#include "hw.h"
+#include "ble_bufsize.h"
+
+
+/******************************************************************************
+ * Application Config
+ ******************************************************************************/
+
+/**< generic parameters ******************************************************/
+/* HCI related defines */
+
+#define ACI_HAL_SET_TX_POWER_LEVEL 0xFC0F
+#define ACI_WRITE_CONFIG_DATA_OPCODE 0xFC0C
+#define ACI_READ_CONFIG_DATA_OPCODE 0xFC0D
+#define MAX_HCI_ACL_PACKET_SIZE (sizeof(TL_PacketHeader_t) + 5 + 251)
+#define HCI_RESET 0x0C03
+
+#ifndef BLE_SHARED_MEM_BYTE_ORDER
+ #define BLE_SHARED_MEM_BYTE_ORDER MSBFIRST
+#endif
+#define BLE_MODULE_SHARED_MEM_BUFFER_SIZE 128
+
+/**
+ * Define Tx Power
+ */
+#define CFG_TX_POWER (0x18) /* -0.15dBm */
+
+/******************************************************************************
+ * BLE Stack
+ ******************************************************************************/
+/**
+ * Maximum number of simultaneous connections that the device will support.
+ * Valid values are from 1 to 8
+ */
+#define CFG_BLE_NUM_LINK 8
+
+/**
+ * Maximum number of Services that can be stored in the GATT database.
+ * Note that the GAP and GATT services are automatically added so this parameter should be 2 plus the number of user services
+ */
+#define CFG_BLE_NUM_GATT_SERVICES 8
+
+/**
+ * Maximum number of Attributes
+ * (i.e. the number of characteristic + the number of characteristic values + the number of descriptors, excluding the services)
+ * that can be stored in the GATT database.
+ * Note that certain characteristics and relative descriptors are added automatically during device initialization
+ * so this parameters should be 9 plus the number of user Attributes
+ */
+#define CFG_BLE_NUM_GATT_ATTRIBUTES 68
+
+/**
+ * Maximum supported ATT_MTU size
+ */
+#define CFG_BLE_MAX_ATT_MTU (156)
+
+/**
+ * Size of the storage area for Attribute values
+ * This value depends on the number of attributes used by application. In particular the sum of the following quantities (in octets) should be made for each attribute:
+ * - attribute value length
+ * - 5, if UUID is 16 bit; 19, if UUID is 128 bit
+ * - 2, if server configuration descriptor is used
+ * - 2*DTM_NUM_LINK, if client configuration descriptor is used
+ * - 2, if extended properties is used
+ * The total amount of memory needed is the sum of the above quantities for each attribute.
+ */
+#define CFG_BLE_ATT_VALUE_ARRAY_SIZE (1344)
+
+/**
+ * Prepare Write List size in terms of number of packet
+ */
+//#define CFG_BLE_PREPARE_WRITE_LIST_SIZE BLE_PREP_WRITE_X_ATT(CFG_BLE_MAX_ATT_MTU)
+#define CFG_BLE_PREPARE_WRITE_LIST_SIZE (0x3A)
+
+/**
+ * Number of allocated memory blocks
+ */
+//#define CFG_BLE_MBLOCK_COUNT (BLE_MBLOCKS_CALC(CFG_BLE_PREPARE_WRITE_LIST_SIZE, CFG_BLE_MAX_ATT_MTU, CFG_BLE_NUM_LINK))
+#define CFG_BLE_MBLOCK_COUNT (0x79)
+/**
+ * Enable or disable the Extended Packet length feature. Valid values are 0 or 1.
+ */
+#define CFG_BLE_DATA_LENGTH_EXTENSION 1
+
+/**
+ * Sleep clock accuracy in Slave mode (ppm value)
+ */
+#define CFG_BLE_SLAVE_SCA 500
+
+/**
+ * Sleep clock accuracy in Master mode
+ * 0 : 251 ppm to 500 ppm
+ * 1 : 151 ppm to 250 ppm
+ * 2 : 101 ppm to 150 ppm
+ * 3 : 76 ppm to 100 ppm
+ * 4 : 51 ppm to 75 ppm
+ * 5 : 31 ppm to 50 ppm
+ * 6 : 21 ppm to 30 ppm
+ * 7 : 0 ppm to 20 ppm
+ */
+#define CFG_BLE_MASTER_SCA 0
+
+/**
+ * Source for the 32 kHz slow speed clock
+ * 1 : internal RO
+ * 0 : external crystal ( no calibration )
+ */
+#define CFG_BLE_LSE_SOURCE 0
+
+/**
+ * Start up time of the high speed (16 or 32 MHz) crystal oscillator in units of 625/256 us (~2.44 us)
+ */
+#define CFG_BLE_HSE_STARTUP_TIME 0x148
+
+/**
+ * Maximum duration of the connection event when the device is in Slave mode in units of 625/256 us (~2.44 us)
+ */
+#define CFG_BLE_MAX_CONN_EVENT_LENGTH ( 0xFFFFFFFF )
+
+/**
+ * Viterbi Mode
+ * 1 : enabled
+ * 0 : disabled
+ */
+#define CFG_BLE_VITERBI_MODE 1
+
+/**
+ * LL Only Mode
+ * 1 : LL Only
+ * 0 : LL + Host
+ */
+#define CFG_BLE_LL_ONLY 1
+
+#endif /* APP_CONF_H */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/src/utility/STM32Cube_FW/ble_bufsize.h b/src/utility/STM32Cube_FW/ble_bufsize.h
new file mode 100644
index 00000000..2961cd99
--- /dev/null
+++ b/src/utility/STM32Cube_FW/ble_bufsize.h
@@ -0,0 +1,161 @@
+/*****************************************************************************
+ * @file ble_bufsize.h
+ * @author MCD Application Team
+ * @brief Definition of BLE stack buffers size
+ *****************************************************************************
+ * @attention
+ *
+ * © Copyright (c) 2019 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software component is licensed by ST under Ultimate Liberty license
+ * SLA0044, the "License"; You may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at:
+ * www.st.com/SLA0044
+ *
+ *****************************************************************************
+ */
+
+#ifndef BLE_BUFSIZE_H__
+#define BLE_BUFSIZE_H__
+
+
+/*
+ * BLE_DEFAULT_ATT_MTU: minimum MTU value that GATT must support.
+ */
+#define BLE_DEFAULT_ATT_MTU 23
+
+/*
+ * BLE_DEFAULT_MAX_ATT_MTU: maximum supported ATT MTU size.
+ */
+#define BLE_DEFAULT_MAX_ATT_MTU 158
+
+/*
+ * BLE_DEFAULT_MAX_ATT_SIZE: maximum attribute size.
+ */
+#define BLE_DEFAULT_MAX_ATT_SIZE 512
+
+/*
+ * BLE_PREP_WRITE_X_ATT: compute how many Prepare Write Request are needed to
+ * write a characteristic with size 'max_att' when the used ATT_MTU value is
+ * equal to BLE_DEFAULT_ATT_MTU (23).
+ */
+#define BLE_PREP_WRITE_X_ATT(max_att) \
+ (DIVC(max_att, BLE_DEFAULT_ATT_MTU - 5) * 2)
+
+/*
+ * BLE_DEFAULT_PREP_WRITE_LIST_SIZE: default minimum Prepare Write List size.
+ */
+#define BLE_DEFAULT_PREP_WRITE_LIST_SIZE \
+ BLE_PREP_WRITE_X_ATT(BLE_DEFAULT_MAX_ATT_SIZE)
+
+/*
+ * BLE_MEM_BLOCK_X_MTU: compute how many memory blocks are needed to compose
+ * an ATT packet with ATT_MTU=mtu.
+ */
+#define BLE_MEM_BLOCK_SIZE 32
+
+#define BLE_MEM_BLOCK_X_TX(mtu) \
+ (DIVC((mtu) + 4U, BLE_MEM_BLOCK_SIZE) + 1U)
+
+#define BLE_MEM_BLOCK_X_RX(mtu, n_link) \
+ ((DIVC((mtu) + 4U, BLE_MEM_BLOCK_SIZE) + 2U) * (n_link) + 1)
+
+#define BLE_MEM_BLOCK_X_MTU(mtu, n_link) \
+ (BLE_MEM_BLOCK_X_TX(mtu) + BLE_MEM_BLOCK_X_RX(mtu, n_link))
+
+/*
+ * BLE_MBLOCKS_SECURE_CONNECTIONS: minimum number of blocks required for
+ * secure connections
+ */
+#define BLE_MBLOCKS_SECURE_CONNECTIONS 4
+
+/*
+ * BLE_MBLOCKS_CALC: minimum number of buffers needed by the stack.
+ * This is the minimum racomanded value and depends on:
+ * - pw: size of Prepare Write List
+ * - mtu: ATT_MTU size
+ * - n_link: maximum number of simultaneous connections
+ */
+#define BLE_MBLOCKS_CALC(pw, mtu, n_link) \
+ ((pw) + MAX(BLE_MEM_BLOCK_X_MTU(mtu, n_link), \
+ BLE_MBLOCKS_SECURE_CONNECTIONS))
+
+/*
+ * BLE_DEFAULT_MBLOCKS_COUNT: default memory blocks count
+ */
+#define BLE_DEFAULT_MBLOCKS_COUNT(n_link) \
+ BLE_MBLOCKS_CALC(BLE_DEFAULT_PREP_WRITE_LIST_SIZE, \
+ BLE_DEFAULT_MAX_ATT_MTU, n_link)
+
+/*
+ * BLE_FIXED_BUFFER_SIZE_BYTES:
+ * A part of the RAM, is dynamically allocated by initializing all the pointers
+ * defined in a global context variable "mem_alloc_ctx_p".
+ * This initialization is made in the Dynamic_allocator functions, which
+ * assign a portion of RAM given by the external application to the above
+ * mentioned "global pointers".
+ *
+ * The size of this Dynamic RAM is made of 2 main components:
+ * - a part that is parameters-dependent (num of links, GATT buffers, ...),
+ * and which value is defined by the following macro;
+ * - a part, that may be considered "fixed", i.e. independent from the above
+ * mentioned parameters.
+*/
+#if (SLAVE_ONLY == 0) && (LL_ONLY == 0)
+ #define BLE_FIXED_BUFFER_SIZE_BYTES 6960 /* Full stack */
+#elif SLAVE_ONLY == 0
+ #define BLE_FIXED_BUFFER_SIZE_BYTES 6256 /* LL only */
+#else
+ #define BLE_FIXED_BUFFER_SIZE_BYTES 6696 /* Slave only */
+#endif
+
+/*
+ * BLE_PER_LINK_SIZE_BYTES: additional memory size used per link
+ */
+#if (SLAVE_ONLY == 0) && (LL_ONLY == 0)
+ #define BLE_PER_LINK_SIZE_BYTES 380 /* Full stack */
+#elif SLAVE_ONLY == 0
+ #define BLE_PER_LINK_SIZE_BYTES 196 /* LL only */
+#else
+ #define BLE_PER_LINK_SIZE_BYTES 332 /* Slave only */
+#endif
+
+/*
+ * BLE_TOTAL_BUFFER_SIZE: this macro returns the amount of memory, in bytes,
+ * needed for the storage of data structures (except GATT database elements)
+ * whose size depends on the number of supported connections.
+ *
+ * @param num_links: Maximum number of simultaneous connections that the device
+ * will support. Valid values are from 1 to 8.
+ *
+ * @param mblocks_count: Number of memory blocks allocated for packets.
+ */
+#define BLE_TOTAL_BUFFER_SIZE(n_link, mblocks_count) \
+ (BLE_FIXED_BUFFER_SIZE_BYTES + \
+ (BLE_PER_LINK_SIZE_BYTES * (n_link)) + \
+ ((BLE_MEM_BLOCK_SIZE + 12) * (mblocks_count)))
+
+/*
+ * BLE_TOTAL_BUFFER_SIZE_GATT: this macro returns the amount of memory,
+ * in bytes, needed for the storage of GATT database elements.
+ *
+ * @param num_gatt_attributes: Maximum number of Attributes (i.e. the number
+ * of characteristic + the number of characteristic values + the number of
+ * descriptors, excluding the services) that can be stored in the GATT
+ * database. Note that certain characteristics and relative descriptors are
+ * added automatically during device initialization so this parameters should
+ * be 9 plus the number of user Attributes
+ *
+ * @param num_gatt_services: Maximum number of Services that can be stored in
+ * the GATT database. Note that the GAP and GATT services are automatically
+ * added so this parameter should be 2 plus the number of user services
+ *
+ * @param att_value_array_size: Size of the storage area for Attribute values.
+ */
+#define BLE_TOTAL_BUFFER_SIZE_GATT(num_gatt_attributes, num_gatt_services, att_value_array_size) \
+ (((((att_value_array_size) - 1) | 3) + 1) + \
+ (40 * (num_gatt_attributes)) + (48 * (num_gatt_services)))
+
+
+#endif /* ! BLE_BUFSIZE_H__ */
diff --git a/src/utility/STM32Cube_FW/hw.h b/src/utility/STM32Cube_FW/hw.h
new file mode 100644
index 00000000..09b12aff
--- /dev/null
+++ b/src/utility/STM32Cube_FW/hw.h
@@ -0,0 +1,97 @@
+/**
+ ******************************************************************************
+ * @file hw.h
+ * @author MCD Application Team
+ * @brief Hardware
+ ******************************************************************************
+ * @attention
+ *
+ * © Copyright (c) 2019 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __HW_H
+#define __HW_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32_def.h"
+#include "stm32wbxx_ll_bus.h"
+#include "stm32wbxx_ll_exti.h"
+#include "stm32wbxx_ll_system.h"
+#include "stm32wbxx_ll_rcc.h"
+#include "stm32wbxx_ll_ipcc.h"
+#include "stm32wbxx_ll_cortex.h"
+#include "stm32wbxx_ll_utils.h"
+#include "stm32wbxx_ll_pwr.h"
+
+/******************************************************************************
+ * HW IPCC
+ ******************************************************************************/
+void HW_IPCC_Enable(void);
+void HW_IPCC_Init(void);
+
+void HW_IPCC_BLE_Init(void);
+void HW_IPCC_BLE_SendCmd(void);
+void HW_IPCC_MM_SendFreeBuf(void (*cb)(void));
+void HW_IPCC_BLE_RxEvtNot(void);
+void HW_IPCC_BLE_SendAclData(void);
+void HW_IPCC_BLE_AclDataAckNot(void);
+
+void HW_IPCC_SYS_Init(void);
+void HW_IPCC_SYS_SendCmd(void);
+void HW_IPCC_SYS_CmdEvtNot(void);
+void HW_IPCC_SYS_EvtNot(void);
+
+void HW_IPCC_THREAD_Init(void);
+void HW_IPCC_OT_SendCmd(void);
+void HW_IPCC_CLI_SendCmd(void);
+void HW_IPCC_THREAD_SendAck(void);
+void HW_IPCC_OT_CmdEvtNot(void);
+void HW_IPCC_CLI_CmdEvtNot(void);
+void HW_IPCC_THREAD_EvtNot(void);
+void HW_IPCC_THREAD_CliSendAck(void);
+void HW_IPCC_THREAD_CliEvtNot(void);
+
+
+void HW_IPCC_LLDTESTS_Init(void);
+void HW_IPCC_LLDTESTS_SendCliCmd(void);
+void HW_IPCC_LLDTESTS_ReceiveCliRsp(void);
+void HW_IPCC_LLDTESTS_SendCliRspAck(void);
+void HW_IPCC_LLDTESTS_ReceiveM0Cmd(void);
+void HW_IPCC_LLDTESTS_SendM0CmdAck(void);
+
+
+void HW_IPCC_LLD_BLE_Init(void);
+void HW_IPCC_LLD_BLE_SendCliCmd(void);
+void HW_IPCC_LLD_BLE_ReceiveCliRsp(void);
+void HW_IPCC_LLD_BLE_SendCliRspAck(void);
+void HW_IPCC_LLD_BLE_ReceiveM0Cmd(void);
+void HW_IPCC_LLD_BLE_SendM0CmdAck(void);
+void HW_IPCC_LLD_BLE_SendCmd(void);
+void HW_IPCC_LLD_BLE_ReceiveRsp(void);
+void HW_IPCC_LLD_BLE_SendRspAck(void);
+
+
+void HW_IPCC_TRACES_Init(void);
+void HW_IPCC_TRACES_EvtNot(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__HW_H */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/src/utility/STM32Cube_FW/hw_ipcc.c b/src/utility/STM32Cube_FW/hw_ipcc.c
new file mode 100644
index 00000000..925075f8
--- /dev/null
+++ b/src/utility/STM32Cube_FW/hw_ipcc.c
@@ -0,0 +1,348 @@
+/**
+ ******************************************************************************
+ * File Name : Target/hw_ipcc.c
+ * Description : Hardware IPCC source file for STM32WPAN Middleware.
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * © Copyright (c) 2020 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software component is licensed by ST under Ultimate Liberty license
+ * SLA0044, the "License"; You may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at:
+ * www.st.com/SLA0044
+ *
+ ******************************************************************************
+ */
+#if defined(STM32WBxx)
+/* Includes ------------------------------------------------------------------*/
+#include "hw.h"
+#include "mbox_def.h"
+
+/* Global variables ---------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+#define HW_IPCC_TX_PENDING( channel ) ( !(LL_C1_IPCC_IsActiveFlag_CHx( IPCC, channel )) ) && (((~(IPCC->C1MR)) & (channel << 16U)))
+#define HW_IPCC_RX_PENDING( channel ) (LL_C2_IPCC_IsActiveFlag_CHx( IPCC, channel )) && (((~(IPCC->C1MR)) & (channel << 0U)))
+
+/* Private macros ------------------------------------------------------------*/
+/* Private typedef -----------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+static void (*FreeBufCb)(void);
+
+/* Private function prototypes -----------------------------------------------*/
+static void HW_IPCC_BLE_EvtHandler(void);
+static void HW_IPCC_BLE_AclDataEvtHandler(void);
+static void HW_IPCC_MM_FreeBufHandler(void);
+static void HW_IPCC_SYS_CmdEvtHandler(void);
+static void HW_IPCC_SYS_EvtHandler(void);
+static void HW_IPCC_TRACES_EvtHandler(void);
+
+#ifdef THREAD_WB
+ static void HW_IPCC_OT_CmdEvtHandler(void);
+ static void HW_IPCC_THREAD_NotEvtHandler(void);
+ static void HW_IPCC_THREAD_CliNotEvtHandler(void);
+#endif
+
+/* Public function definition -----------------------------------------------*/
+
+/******************************************************************************
+ * INTERRUPT HANDLER
+ ******************************************************************************/
+
+void IPCC_C1_RX_IRQHandler(void)
+{
+ if (HW_IPCC_RX_PENDING(HW_IPCC_SYSTEM_EVENT_CHANNEL)) {
+ HW_IPCC_SYS_EvtHandler();
+ }
+#ifdef THREAD_WB
+ else if (HW_IPCC_RX_PENDING(HW_IPCC_THREAD_NOTIFICATION_ACK_CHANNEL)) {
+ HW_IPCC_THREAD_NotEvtHandler();
+ } else if (HW_IPCC_RX_PENDING(HW_IPCC_THREAD_CLI_NOTIFICATION_ACK_CHANNEL)) {
+ HW_IPCC_THREAD_CliNotEvtHandler();
+ }
+#endif /* THREAD_WB */
+ else if (HW_IPCC_RX_PENDING(HW_IPCC_BLE_EVENT_CHANNEL)) {
+ HW_IPCC_BLE_EvtHandler();
+ } else if (HW_IPCC_RX_PENDING(HW_IPCC_TRACES_CHANNEL)) {
+ HW_IPCC_TRACES_EvtHandler();
+ }
+}
+
+void IPCC_C1_TX_IRQHandler(void)
+{
+ if (HW_IPCC_TX_PENDING(HW_IPCC_SYSTEM_CMD_RSP_CHANNEL)) {
+ HW_IPCC_SYS_CmdEvtHandler();
+ }
+#ifdef THREAD_WB
+ else if (HW_IPCC_TX_PENDING(HW_IPCC_THREAD_OT_CMD_RSP_CHANNEL)) {
+ HW_IPCC_OT_CmdEvtHandler();
+ }
+#endif /* THREAD_WB */
+ else if (HW_IPCC_TX_PENDING(HW_IPCC_SYSTEM_CMD_RSP_CHANNEL)) {
+ HW_IPCC_SYS_CmdEvtHandler();
+ } else if (HW_IPCC_TX_PENDING(HW_IPCC_MM_RELEASE_BUFFER_CHANNEL)) {
+ HW_IPCC_MM_FreeBufHandler();
+ } else if (HW_IPCC_TX_PENDING(HW_IPCC_HCI_ACL_DATA_CHANNEL)) {
+ HW_IPCC_BLE_AclDataEvtHandler();
+ }
+}
+
+/******************************************************************************
+ * GENERAL
+ ******************************************************************************/
+void HW_IPCC_Enable(void)
+{
+ /**
+ * Such as IPCC IP available to the CPU2, it is required to keep the IPCC clock running
+ when FUS is running on CPU2 and CPU1 enters deep sleep mode
+ */
+ LL_C2_AHB3_GRP1_EnableClock(LL_C2_AHB3_GRP1_PERIPH_IPCC);
+
+ /**
+ * When the device is out of standby, it is required to use the EXTI mechanism to wakeup CPU2
+ */
+ LL_C2_EXTI_EnableEvent_32_63(LL_EXTI_LINE_41);
+ LL_EXTI_EnableRisingTrig_32_63(LL_EXTI_LINE_41);
+
+ /**
+ * In case the SBSFU is implemented, it may have already set the C2BOOT bit to startup the CPU2.
+ * In that case, to keep the mechanism transparent to the user application, it shall call the system command
+ * SHCI_C2_Reinit( ) before jumping to the application.
+ * When the CPU2 receives that command, it waits for its event input to be set to restart the CPU2 firmware.
+ * This is required because once C2BOOT has been set once, a clear/set on C2BOOT has no effect.
+ * When SHCI_C2_Reinit( ) is not called, generating an event to the CPU2 does not have any effect
+ * So, by default, the application shall both set the event flag and set the C2BOOT bit.
+ */
+ __SEV(); /* Set the internal event flag and send an event to the CPU2 */
+ __WFE(); /* Clear the internal event flag */
+ LL_PWR_EnableBootC2();
+
+ return;
+}
+
+void HW_IPCC_Init(void)
+{
+ LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_IPCC);
+
+ LL_C1_IPCC_EnableIT_RXO(IPCC);
+ LL_C1_IPCC_EnableIT_TXF(IPCC);
+
+ HAL_NVIC_EnableIRQ(IPCC_C1_RX_IRQn);
+ HAL_NVIC_EnableIRQ(IPCC_C1_TX_IRQn);
+
+ return;
+}
+
+/******************************************************************************
+ * BLE
+ ******************************************************************************/
+void HW_IPCC_BLE_Init(void)
+{
+ LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_BLE_EVENT_CHANNEL);
+
+ return;
+}
+
+void HW_IPCC_BLE_SendCmd(void)
+{
+ LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_BLE_CMD_CHANNEL);
+
+ return;
+}
+
+static void HW_IPCC_BLE_EvtHandler(void)
+{
+ HW_IPCC_BLE_RxEvtNot();
+
+ LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_BLE_EVENT_CHANNEL);
+
+ return;
+}
+
+void HW_IPCC_BLE_SendAclData(void)
+{
+ LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_HCI_ACL_DATA_CHANNEL);
+ LL_C1_IPCC_EnableTransmitChannel(IPCC, HW_IPCC_HCI_ACL_DATA_CHANNEL);
+
+ return;
+}
+
+static void HW_IPCC_BLE_AclDataEvtHandler(void)
+{
+ LL_C1_IPCC_DisableTransmitChannel(IPCC, HW_IPCC_HCI_ACL_DATA_CHANNEL);
+
+ HW_IPCC_BLE_AclDataAckNot();
+
+ return;
+}
+
+__WEAK void HW_IPCC_BLE_AclDataAckNot(void) {};
+__WEAK void HW_IPCC_BLE_RxEvtNot(void) {};
+
+/******************************************************************************
+ * SYSTEM
+ ******************************************************************************/
+void HW_IPCC_SYS_Init(void)
+{
+ LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_SYSTEM_EVENT_CHANNEL);
+
+ return;
+}
+
+void HW_IPCC_SYS_SendCmd(void)
+{
+ LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_SYSTEM_CMD_RSP_CHANNEL);
+ LL_C1_IPCC_EnableTransmitChannel(IPCC, HW_IPCC_SYSTEM_CMD_RSP_CHANNEL);
+
+ return;
+}
+
+static void HW_IPCC_SYS_CmdEvtHandler(void)
+{
+ LL_C1_IPCC_DisableTransmitChannel(IPCC, HW_IPCC_SYSTEM_CMD_RSP_CHANNEL);
+
+ HW_IPCC_SYS_CmdEvtNot();
+
+ return;
+}
+
+static void HW_IPCC_SYS_EvtHandler(void)
+{
+ HW_IPCC_SYS_EvtNot();
+
+ LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_SYSTEM_EVENT_CHANNEL);
+
+ return;
+}
+
+__WEAK void HW_IPCC_SYS_CmdEvtNot(void) {};
+__WEAK void HW_IPCC_SYS_EvtNot(void) {};
+
+/******************************************************************************
+ * THREAD
+ ******************************************************************************/
+#ifdef THREAD_WB
+void HW_IPCC_THREAD_Init(void)
+{
+ LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_THREAD_NOTIFICATION_ACK_CHANNEL);
+ LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_THREAD_CLI_NOTIFICATION_ACK_CHANNEL);
+
+ return;
+}
+
+void HW_IPCC_OT_SendCmd(void)
+{
+ LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_THREAD_OT_CMD_RSP_CHANNEL);
+ LL_C1_IPCC_EnableTransmitChannel(IPCC, HW_IPCC_THREAD_OT_CMD_RSP_CHANNEL);
+
+ return;
+}
+
+void HW_IPCC_CLI_SendCmd(void)
+{
+ LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_THREAD_CLI_CMD_CHANNEL);
+
+ return;
+}
+
+void HW_IPCC_THREAD_SendAck(void)
+{
+ LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_THREAD_NOTIFICATION_ACK_CHANNEL);
+ LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_THREAD_NOTIFICATION_ACK_CHANNEL);
+
+ return;
+}
+
+void HW_IPCC_THREAD_CliSendAck(void)
+{
+ LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_THREAD_CLI_NOTIFICATION_ACK_CHANNEL);
+ LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_THREAD_CLI_NOTIFICATION_ACK_CHANNEL);
+
+ return;
+}
+
+static void HW_IPCC_OT_CmdEvtHandler(void)
+{
+ LL_C1_IPCC_DisableTransmitChannel(IPCC, HW_IPCC_THREAD_OT_CMD_RSP_CHANNEL);
+
+ HW_IPCC_OT_CmdEvtNot();
+
+ return;
+}
+
+static void HW_IPCC_THREAD_NotEvtHandler(void)
+{
+ LL_C1_IPCC_DisableReceiveChannel(IPCC, HW_IPCC_THREAD_NOTIFICATION_ACK_CHANNEL);
+
+ HW_IPCC_THREAD_EvtNot();
+
+ return;
+}
+
+static void HW_IPCC_THREAD_CliNotEvtHandler(void)
+{
+ LL_C1_IPCC_DisableReceiveChannel(IPCC, HW_IPCC_THREAD_CLI_NOTIFICATION_ACK_CHANNEL);
+
+ HW_IPCC_THREAD_CliEvtNot();
+
+ return;
+}
+
+__WEAK void HW_IPCC_OT_CmdEvtNot(void) {};
+__WEAK void HW_IPCC_CLI_CmdEvtNot(void) {};
+__WEAK void HW_IPCC_THREAD_EvtNot(void) {};
+
+#endif /* THREAD_WB */
+
+/******************************************************************************
+ * MEMORY MANAGER
+ ******************************************************************************/
+void HW_IPCC_MM_SendFreeBuf(void (*cb)(void))
+{
+ if (LL_C1_IPCC_IsActiveFlag_CHx(IPCC, HW_IPCC_MM_RELEASE_BUFFER_CHANNEL)) {
+ FreeBufCb = cb;
+ LL_C1_IPCC_EnableTransmitChannel(IPCC, HW_IPCC_MM_RELEASE_BUFFER_CHANNEL);
+ } else {
+ cb();
+
+ LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_MM_RELEASE_BUFFER_CHANNEL);
+ }
+
+ return;
+}
+
+static void HW_IPCC_MM_FreeBufHandler(void)
+{
+ LL_C1_IPCC_DisableTransmitChannel(IPCC, HW_IPCC_MM_RELEASE_BUFFER_CHANNEL);
+
+ FreeBufCb();
+
+ LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_MM_RELEASE_BUFFER_CHANNEL);
+
+ return;
+}
+
+/******************************************************************************
+ * TRACES
+ ******************************************************************************/
+void HW_IPCC_TRACES_Init(void)
+{
+ LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_TRACES_CHANNEL);
+
+ return;
+}
+
+static void HW_IPCC_TRACES_EvtHandler(void)
+{
+ HW_IPCC_TRACES_EvtNot();
+
+ LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_TRACES_CHANNEL);
+
+ return;
+}
+
+__WEAK void HW_IPCC_TRACES_EvtNot(void) {};
+#endif /* STM32WBxx */
+/******************* (C) COPYRIGHT 2019 STMicroelectronics *****END OF FILE****/
diff --git a/src/utility/STM32Cube_FW/mbox_def.h b/src/utility/STM32Cube_FW/mbox_def.h
new file mode 100644
index 00000000..d5a7d46b
--- /dev/null
+++ b/src/utility/STM32Cube_FW/mbox_def.h
@@ -0,0 +1,212 @@
+/**
+ ******************************************************************************
+ * @file mbox_def.h
+ * @author MCD Application Team
+ * @brief Mailbox definition
+ ******************************************************************************
+ * @attention
+ *
+ * © Copyright (c) 2019 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __MBOX_H
+#define __MBOX_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "stm32_wpan_common.h"
+
+/**
+ * This file shall be identical between the CPU1 and the CPU2
+ */
+
+/**
+ *********************************************************************************
+ * TABLES
+ *********************************************************************************
+ */
+
+/**
+ * Version
+ * [0:3] = Build - 0: Untracked - 15:Released - x: Tracked version
+ * [4:7] = branch - 0: Mass Market - x: ...
+ * [8:15] = Subversion
+ * [16:23] = Version minor
+ * [24:31] = Version major
+ *
+ * Memory Size
+ * [0:7] = Flash ( Number of 4k sector)
+ * [8:15] = Reserved ( Shall be set to 0 - may be used as flash extension )
+ * [16:23] = SRAM2b ( Number of 1k sector)
+ * [24:31] = SRAM2a ( Number of 1k sector)
+ */
+typedef PACKED_STRUCT {
+ uint32_t Version;
+} MB_SafeBootInfoTable_t;
+
+typedef PACKED_STRUCT {
+ uint32_t Version;
+ uint32_t MemorySize;
+ uint32_t FusInfo;
+} MB_FusInfoTable_t;
+
+typedef PACKED_STRUCT {
+ uint32_t Version;
+ uint32_t MemorySize;
+ uint32_t InfoStack;
+ uint32_t Reserved;
+} MB_WirelessFwInfoTable_t;
+
+typedef struct {
+ MB_SafeBootInfoTable_t SafeBootInfoTable;
+ MB_FusInfoTable_t FusInfoTable;
+ MB_WirelessFwInfoTable_t WirelessFwInfoTable;
+} MB_DeviceInfoTable_t;
+
+typedef struct {
+ uint8_t *pcmd_buffer;
+ uint8_t *pcs_buffer;
+ uint8_t *pevt_queue;
+ uint8_t *phci_acl_data_buffer;
+} MB_BleTable_t;
+
+typedef struct {
+ uint8_t *notack_buffer;
+ uint8_t *clicmdrsp_buffer;
+ uint8_t *otcmdrsp_buffer;
+} MB_ThreadTable_t;
+
+typedef struct {
+ uint8_t *clicmdrsp_buffer;
+ uint8_t *m0cmd_buffer;
+} MB_LldTestsTable_t;
+
+typedef struct {
+ uint8_t *cmdrsp_buffer;
+ uint8_t *m0cmd_buffer;
+} MB_LldBleTable_t;
+
+/**
+ * msg
+ * [0:7] = cmd/evt
+ * [8:31] = Reserved
+ */
+typedef struct {
+ uint8_t *pcmd_buffer;
+ uint8_t *sys_queue;
+} MB_SysTable_t;
+
+typedef struct {
+ uint8_t *spare_ble_buffer;
+ uint8_t *spare_sys_buffer;
+ uint8_t *blepool;
+ uint32_t blepoolsize;
+ uint8_t *pevt_free_buffer_queue;
+ uint8_t *traces_evt_pool;
+ uint32_t tracespoolsize;
+} MB_MemManagerTable_t;
+
+typedef struct {
+ uint8_t *traces_queue;
+} MB_TracesTable_t;
+
+typedef struct {
+ MB_DeviceInfoTable_t *p_device_info_table;
+ MB_BleTable_t *p_ble_table;
+ MB_ThreadTable_t *p_thread_table;
+ MB_SysTable_t *p_sys_table;
+ MB_MemManagerTable_t *p_mem_manager_table;
+ MB_TracesTable_t *p_traces_table;
+ MB_LldTestsTable_t *p_lld_tests_table;
+ MB_LldBleTable_t *p_lld_ble_table;
+} MB_RefTable_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ *********************************************************************************
+ * IPCC CHANNELS
+ *********************************************************************************
+ */
+
+/* CPU1 CPU2
+ * | (SYSTEM) |
+ * |----HW_IPCC_SYSTEM_CMD_RSP_CHANNEL-------------->|
+ * | |
+ * |<---HW_IPCC_SYSTEM_EVENT_CHANNEL-----------------|
+ * | |
+ * | (THREAD) |
+ * |----HW_IPCC_THREAD_OT_CMD_RSP_CHANNEL----------->|
+ * | |
+ * |----HW_IPCC_THREAD_CLI_CMD_CHANNEL-------------->|
+ * | |
+ * |<---HW_IPCC_THREAD_NOTIFICATION_ACK_CHANNEL------|
+ * | |
+ * |<---HW_IPCC_THREAD_CLI_NOTIFICATION_ACK_CHANNEL--|
+ * | |
+ * | (BLE) |
+ * |----HW_IPCC_BLE_CMD_CHANNEL--------------------->|
+ * | |
+ * |----HW_IPCC_HCI_ACL_DATA_CHANNEL---------------->|
+ * | |
+ * |<---HW_IPCC_BLE_EVENT_CHANNEL--------------------|
+ * | |
+ * | (LLD BLE) |
+ * |----HW_IPCC_LLD_BLE_CMD_CHANNEL----------------->|
+ * | |
+ * |<---HW_IPCC_LLD_BLE_RSP_CHANNEL------------------|
+ * | |
+ * |<---HW_IPCC_LLD_BLE_M0_CMD_CHANNEL---------------|
+ * | |
+ * | (BUFFER) |
+ * |----HW_IPCC_MM_RELEASE_BUFFER_CHANNE------------>|
+ * | |
+ * | (TRACE) |
+ * |<----HW_IPCC_TRACES_CHANNEL----------------------|
+ * | |
+ *
+ *
+ *
+ */
+
+
+
+/** CPU1 */
+#define HW_IPCC_BLE_CMD_CHANNEL LL_IPCC_CHANNEL_1
+#define HW_IPCC_SYSTEM_CMD_RSP_CHANNEL LL_IPCC_CHANNEL_2
+#define HW_IPCC_THREAD_OT_CMD_RSP_CHANNEL LL_IPCC_CHANNEL_3
+#define HW_IPCC_MM_RELEASE_BUFFER_CHANNEL LL_IPCC_CHANNEL_4
+#define HW_IPCC_THREAD_CLI_CMD_CHANNEL LL_IPCC_CHANNEL_5
+#define HW_IPCC_LLDTESTS_CLI_CMD_CHANNEL LL_IPCC_CHANNEL_5
+#define HW_IPCC_LLD_BLE_CLI_CMD_CHANNEL LL_IPCC_CHANNEL_5
+#define HW_IPCC_LLD_BLE_CMD_CHANNEL LL_IPCC_CHANNEL_5
+#define HW_IPCC_HCI_ACL_DATA_CHANNEL LL_IPCC_CHANNEL_6
+
+/** CPU2 */
+#define HW_IPCC_BLE_EVENT_CHANNEL LL_IPCC_CHANNEL_1
+#define HW_IPCC_SYSTEM_EVENT_CHANNEL LL_IPCC_CHANNEL_2
+#define HW_IPCC_THREAD_NOTIFICATION_ACK_CHANNEL LL_IPCC_CHANNEL_3
+#define HW_IPCC_LLDTESTS_M0_CMD_CHANNEL LL_IPCC_CHANNEL_3
+#define HW_IPCC_LLD_BLE_M0_CMD_CHANNEL LL_IPCC_CHANNEL_3
+#define HW_IPCC_TRACES_CHANNEL LL_IPCC_CHANNEL_4
+#define HW_IPCC_THREAD_CLI_NOTIFICATION_ACK_CHANNEL LL_IPCC_CHANNEL_5
+#define HW_IPCC_LLDTESTS_CLI_RSP_CHANNEL LL_IPCC_CHANNEL_5
+#define HW_IPCC_LLD_BLE_CLI_RSP_CHANNEL LL_IPCC_CHANNEL_5
+#define HW_IPCC_LLD_BLE_RSP_CHANNEL LL_IPCC_CHANNEL_5
+#endif /*__MBOX_H */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/src/utility/STM32Cube_FW/shci.c b/src/utility/STM32Cube_FW/shci.c
new file mode 100644
index 00000000..d23157f2
--- /dev/null
+++ b/src/utility/STM32Cube_FW/shci.c
@@ -0,0 +1,567 @@
+/**
+ ******************************************************************************
+ * @file shci.c
+ * @author MCD Application Team
+ * @brief HCI command for the system channel
+ ******************************************************************************
+ * @attention
+ *
+ * © Copyright (c) 2019 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+#if defined(STM32WBxx)
+/* Includes ------------------------------------------------------------------*/
+#include "stm32_wpan_common.h"
+
+#include "shci_tl.h"
+#include "shci.h"
+#include "stm32wbxx.h"
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Global variables ----------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Local Functions Definition ------------------------------------------------------*/
+/* Public Functions Definition ------------------------------------------------------*/
+
+/**
+ * C2 COMMAND
+ * These commands are sent to the CPU2
+ */
+uint8_t SHCI_C2_FUS_GetState(SHCI_FUS_GetState_ErrorCode_t *p_error_code)
+{
+ /**
+ * A command status event + payload has the same size than the expected command complete
+ */
+ uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE + 1];
+ TL_EvtPacket_t *p_rsp;
+
+ p_rsp = (TL_EvtPacket_t *)local_buffer;
+
+ shci_send(SHCI_OPCODE_C2_FUS_GET_STATE,
+ 0,
+ 0,
+ p_rsp);
+
+ if (p_error_code != 0) {
+ *p_error_code = (SHCI_FUS_GetState_ErrorCode_t)(((TL_CcEvt_t *)(p_rsp->evtserial.evt.payload))->payload[1]);
+ }
+
+ return (((TL_CcEvt_t *)(p_rsp->evtserial.evt.payload))->payload[0]);
+}
+
+SHCI_CmdStatus_t SHCI_C2_FUS_FwUpgrade(uint32_t fw_src_add, uint32_t fw_dest_add)
+{
+ /**
+ * TL_BLEEVT_CS_BUFFER_SIZE is 15 bytes so it is large enough to hold the 8 bytes of command parameters
+ * Buffer is large enough to hold command complete without payload
+ */
+ uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
+ TL_EvtPacket_t *p_rsp;
+ uint32_t *p_cmd;
+ uint8_t cmd_length;
+
+ p_cmd = (uint32_t *)local_buffer;
+ cmd_length = 0;
+
+ if (fw_src_add != 0) {
+ *p_cmd = fw_src_add;
+ cmd_length += 4;
+ }
+
+ if (fw_dest_add != 0) {
+ *(p_cmd + 1) = fw_dest_add;
+ cmd_length += 4;
+ }
+
+ p_rsp = (TL_EvtPacket_t *)local_buffer;
+
+ shci_send(SHCI_OPCODE_C2_FUS_FW_UPGRADE,
+ cmd_length,
+ local_buffer,
+ p_rsp);
+
+ return (SHCI_CmdStatus_t)(((TL_CcEvt_t *)(p_rsp->evtserial.evt.payload))->payload[0]);
+}
+
+SHCI_CmdStatus_t SHCI_C2_FUS_FwDelete(void)
+{
+ /**
+ * Buffer is large enough to hold command complete without payload
+ */
+ uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
+ TL_EvtPacket_t *p_rsp;
+
+ p_rsp = (TL_EvtPacket_t *)local_buffer;
+
+ shci_send(SHCI_OPCODE_C2_FUS_FW_DELETE,
+ 0,
+ 0,
+ p_rsp);
+
+ return (SHCI_CmdStatus_t)(((TL_CcEvt_t *)(p_rsp->evtserial.evt.payload))->payload[0]);
+}
+
+SHCI_CmdStatus_t SHCI_C2_FUS_UpdateAuthKey(SHCI_C2_FUS_UpdateAuthKey_Cmd_Param_t *pParam)
+{
+ /**
+ * Buffer is large enough to hold command complete without payload
+ */
+ uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
+ TL_EvtPacket_t *p_rsp;
+
+ p_rsp = (TL_EvtPacket_t *)local_buffer;
+
+ shci_send(SHCI_OPCODE_C2_FUS_UPDATE_AUTH_KEY,
+ sizeof(SHCI_C2_FUS_UpdateAuthKey_Cmd_Param_t),
+ (uint8_t *)pParam,
+ p_rsp);
+
+ return (SHCI_CmdStatus_t)(((TL_CcEvt_t *)(p_rsp->evtserial.evt.payload))->payload[0]);
+}
+
+SHCI_CmdStatus_t SHCI_C2_FUS_LockAuthKey(void)
+{
+ /**
+ * Buffer is large enough to hold command complete without payload
+ */
+ uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
+ TL_EvtPacket_t *p_rsp;
+
+ p_rsp = (TL_EvtPacket_t *)local_buffer;
+
+ shci_send(SHCI_OPCODE_C2_FUS_LOCK_AUTH_KEY,
+ 0,
+ 0,
+ p_rsp);
+
+ return (SHCI_CmdStatus_t)(((TL_CcEvt_t *)(p_rsp->evtserial.evt.payload))->payload[0]);
+}
+
+SHCI_CmdStatus_t SHCI_C2_FUS_StoreUsrKey(SHCI_C2_FUS_StoreUsrKey_Cmd_Param_t *pParam, uint8_t *p_key_index)
+{
+ /**
+ * Buffer is large enough to hold command complete without payload
+ */
+ uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE + 1];
+ TL_EvtPacket_t *p_rsp;
+ uint8_t local_payload_len;
+
+ if (pParam->KeyType == KEYTYPE_ENCRYPTED) {
+ /**
+ * When the key is encrypted, the 12 bytes IV Key is included in the payload as well
+ * The IV key is always 12 bytes
+ */
+ local_payload_len = pParam->KeySize + 2 + 12;
+ } else {
+ local_payload_len = pParam->KeySize + 2;
+ }
+
+ p_rsp = (TL_EvtPacket_t *)local_buffer;
+
+ shci_send(SHCI_OPCODE_C2_FUS_STORE_USR_KEY,
+ local_payload_len,
+ (uint8_t *)pParam,
+ p_rsp);
+
+ *p_key_index = (((TL_CcEvt_t *)(p_rsp->evtserial.evt.payload))->payload[1]);
+
+ return (SHCI_CmdStatus_t)(((TL_CcEvt_t *)(p_rsp->evtserial.evt.payload))->payload[0]);
+}
+
+SHCI_CmdStatus_t SHCI_C2_FUS_LoadUsrKey(uint8_t key_index)
+{
+ /**
+ * Buffer is large enough to hold command complete without payload
+ */
+ uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
+ TL_EvtPacket_t *p_rsp;
+
+ p_rsp = (TL_EvtPacket_t *)local_buffer;
+
+ local_buffer[0] = key_index;
+
+ shci_send(SHCI_OPCODE_C2_FUS_LOAD_USR_KEY,
+ 1,
+ local_buffer,
+ p_rsp);
+
+ return (SHCI_CmdStatus_t)(((TL_CcEvt_t *)(p_rsp->evtserial.evt.payload))->payload[0]);
+}
+
+SHCI_CmdStatus_t SHCI_C2_FUS_StartWs(void)
+{
+ /**
+ * Buffer is large enough to hold command complete without payload
+ */
+ uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
+ TL_EvtPacket_t *p_rsp;
+
+ p_rsp = (TL_EvtPacket_t *)local_buffer;
+
+ shci_send(SHCI_OPCODE_C2_FUS_START_WS,
+ 0,
+ 0,
+ p_rsp);
+
+ return (SHCI_CmdStatus_t)(((TL_CcEvt_t *)(p_rsp->evtserial.evt.payload))->payload[0]);
+}
+
+
+SHCI_CmdStatus_t SHCI_C2_FUS_LockUsrKey(uint8_t key_index)
+{
+ /**
+ * Buffer is large enough to hold command complete without payload
+ */
+ uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
+ TL_EvtPacket_t *p_rsp;
+
+ p_rsp = (TL_EvtPacket_t *)local_buffer;
+
+ local_buffer[0] = key_index;
+
+ shci_send(SHCI_OPCODE_C2_FUS_LOCK_USR_KEY,
+ 1,
+ local_buffer,
+ p_rsp);
+
+ return (SHCI_CmdStatus_t)(((TL_CcEvt_t *)(p_rsp->evtserial.evt.payload))->payload[0]);
+}
+
+SHCI_CmdStatus_t SHCI_C2_BLE_Init(SHCI_C2_Ble_Init_Cmd_Packet_t *pCmdPacket)
+{
+ /**
+ * Buffer is large enough to hold command complete without payload
+ */
+ uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
+ TL_EvtPacket_t *p_rsp;
+
+ p_rsp = (TL_EvtPacket_t *)local_buffer;
+
+ shci_send(SHCI_OPCODE_C2_BLE_INIT,
+ sizeof(SHCI_C2_Ble_Init_Cmd_Param_t),
+ (uint8_t *)&pCmdPacket->Param,
+ p_rsp);
+
+ return (SHCI_CmdStatus_t)(((TL_CcEvt_t *)(p_rsp->evtserial.evt.payload))->payload[0]);
+}
+
+SHCI_CmdStatus_t SHCI_C2_THREAD_Init(void)
+{
+ /**
+ * Buffer is large enough to hold command complete without payload
+ */
+ uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
+ TL_EvtPacket_t *p_rsp;
+
+ p_rsp = (TL_EvtPacket_t *)local_buffer;
+
+ shci_send(SHCI_OPCODE_C2_THREAD_INIT,
+ 0,
+ 0,
+ p_rsp);
+
+ return (SHCI_CmdStatus_t)(((TL_CcEvt_t *)(p_rsp->evtserial.evt.payload))->payload[0]);
+}
+
+SHCI_CmdStatus_t SHCI_C2_LLDTESTS_Init(uint8_t param_size, uint8_t *p_param)
+{
+ /**
+ * Buffer is large enough to hold command complete without payload
+ */
+ uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
+ TL_EvtPacket_t *p_rsp;
+
+ p_rsp = (TL_EvtPacket_t *)local_buffer;
+
+ shci_send(SHCI_OPCODE_C2_LLD_TESTS_INIT,
+ param_size,
+ p_param,
+ p_rsp);
+
+ return (SHCI_CmdStatus_t)(((TL_CcEvt_t *)(p_rsp->evtserial.evt.payload))->payload[0]);
+}
+
+SHCI_CmdStatus_t SHCI_C2_LLD_BLE_Init(uint8_t param_size, uint8_t *p_param)
+{
+ /**
+ * Buffer is large enough to hold command complete without payload
+ */
+ uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
+ TL_EvtPacket_t *p_rsp;
+
+ p_rsp = (TL_EvtPacket_t *)local_buffer;
+
+ shci_send(SHCI_OPCODE_C2_LLD_BLE_INIT,
+ param_size,
+ p_param,
+ p_rsp);
+
+ return (SHCI_CmdStatus_t)(((TL_CcEvt_t *)(p_rsp->evtserial.evt.payload))->payload[0]);
+}
+
+SHCI_CmdStatus_t SHCI_C2_DEBUG_Init(SHCI_C2_DEBUG_Init_Cmd_Packet_t *pCmdPacket)
+{
+ /**
+ * Buffer is large enough to hold command complete without payload
+ */
+ uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
+ TL_EvtPacket_t *p_rsp;
+
+ p_rsp = (TL_EvtPacket_t *)local_buffer;
+
+ shci_send(SHCI_OPCODE_C2_DEBUG_INIT,
+ sizeof(SHCI_C2_DEBUG_init_Cmd_Param_t),
+ (uint8_t *)&pCmdPacket->Param,
+ p_rsp);
+
+ return (SHCI_CmdStatus_t)(((TL_CcEvt_t *)(p_rsp->evtserial.evt.payload))->payload[0]);
+}
+
+SHCI_CmdStatus_t SHCI_C2_FLASH_EraseActivity(SHCI_EraseActivity_t erase_activity)
+{
+ /**
+ * Buffer is large enough to hold command complete without payload
+ */
+ uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
+ TL_EvtPacket_t *p_rsp;
+
+ p_rsp = (TL_EvtPacket_t *)local_buffer;
+
+ local_buffer[0] = erase_activity;
+
+ shci_send(SHCI_OPCODE_C2_FLASH_ERASE_ACTIVITY,
+ 1,
+ local_buffer,
+ p_rsp);
+
+ return (SHCI_CmdStatus_t)(((TL_CcEvt_t *)(p_rsp->evtserial.evt.payload))->payload[0]);
+}
+
+SHCI_CmdStatus_t SHCI_C2_CONCURRENT_SetMode(SHCI_C2_CONCURRENT_Mode_Param_t Mode)
+{
+ /**
+ * Buffer is large enough to hold command complete without payload
+ */
+ uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
+ TL_EvtPacket_t *p_rsp;
+
+ p_rsp = (TL_EvtPacket_t *)local_buffer;
+
+ local_buffer[0] = Mode;
+
+ shci_send(SHCI_OPCODE_C2_CONCURRENT_SET_MODE,
+ 1,
+ local_buffer,
+ p_rsp);
+
+ return (SHCI_CmdStatus_t)(((TL_CcEvt_t *)(p_rsp->evtserial.evt.payload))->payload[0]);
+}
+
+SHCI_CmdStatus_t SHCI_C2_FLASH_StoreData(SHCI_C2_FLASH_Ip_t Ip)
+{
+ /**
+ * Buffer is large enough to hold command complete without payload
+ */
+ uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
+ TL_EvtPacket_t *p_rsp;
+
+ p_rsp = (TL_EvtPacket_t *)local_buffer;
+
+ local_buffer[0] = Ip;
+
+ shci_send(SHCI_OPCODE_C2_FLASH_STORE_DATA,
+ 1,
+ local_buffer,
+ p_rsp);
+
+ return (SHCI_CmdStatus_t)(((TL_CcEvt_t *)(p_rsp->evtserial.evt.payload))->payload[0]);
+}
+
+SHCI_CmdStatus_t SHCI_C2_FLASH_EraseData(SHCI_C2_FLASH_Ip_t Ip)
+{
+ /**
+ * Buffer is large enough to hold command complete without payload
+ */
+ uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
+ TL_EvtPacket_t *p_rsp;
+
+ p_rsp = (TL_EvtPacket_t *)local_buffer;
+
+ local_buffer[0] = Ip;
+
+ shci_send(SHCI_OPCODE_C2_FLASH_ERASE_DATA,
+ 1,
+ local_buffer,
+ p_rsp);
+
+ return (SHCI_CmdStatus_t)(((TL_CcEvt_t *)(p_rsp->evtserial.evt.payload))->payload[0]);
+}
+
+SHCI_CmdStatus_t SHCI_C2_RADIO_AllowLowPower(SHCI_C2_FLASH_Ip_t Ip, uint8_t FlagRadioLowPowerOn)
+{
+ /**
+ * Buffer is large enough to hold command complete without payload
+ */
+ uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
+ TL_EvtPacket_t *p_rsp;
+
+ p_rsp = (TL_EvtPacket_t *)local_buffer;
+
+ local_buffer[0] = Ip;
+ local_buffer[1] = FlagRadioLowPowerOn;
+
+ shci_send(SHCI_OPCODE_C2_RADIO_ALLOW_LOW_POWER,
+ 2,
+ local_buffer,
+ p_rsp);
+
+ return (SHCI_CmdStatus_t)(((TL_CcEvt_t *)(p_rsp->evtserial.evt.payload))->payload[0]);
+}
+
+SHCI_CmdStatus_t SHCI_C2_Reinit(void)
+{
+ /**
+ * Buffer is large enough to hold command complete without payload
+ */
+ uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
+ TL_EvtPacket_t *p_rsp;
+
+ p_rsp = (TL_EvtPacket_t *)local_buffer;
+
+ shci_send(SHCI_OPCODE_C2_REINIT,
+ 0,
+ 0,
+ p_rsp);
+
+ return (SHCI_CmdStatus_t)(((TL_CcEvt_t *)(p_rsp->evtserial.evt.payload))->payload[0]);
+}
+
+SHCI_CmdStatus_t SHCI_C2_ExtpaConfig(uint32_t gpio_port, uint16_t gpio_pin_number, uint8_t gpio_polarity, uint8_t gpio_status)
+{
+ /**
+ * TL_BLEEVT_CS_BUFFER_SIZE is 15 bytes so it is large enough to hold the 8 bytes of command parameters
+ * Buffer is large enough to hold command complete without payload
+ */
+ uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
+ TL_EvtPacket_t *p_rsp;
+
+ p_rsp = (TL_EvtPacket_t *)local_buffer;
+
+ ((SHCI_C2_EXTPA_CONFIG_Cmd_Param_t *)local_buffer)->gpio_port = gpio_port;
+ ((SHCI_C2_EXTPA_CONFIG_Cmd_Param_t *)local_buffer)->gpio_pin_number = gpio_pin_number;
+ ((SHCI_C2_EXTPA_CONFIG_Cmd_Param_t *)local_buffer)->gpio_polarity = gpio_polarity;
+ ((SHCI_C2_EXTPA_CONFIG_Cmd_Param_t *)local_buffer)->gpio_status = gpio_status;
+
+ shci_send(SHCI_OPCODE_C2_EXTPA_CONFIG,
+ 8,
+ local_buffer,
+ p_rsp);
+
+ return (SHCI_CmdStatus_t)(((TL_CcEvt_t *)(p_rsp->evtserial.evt.payload))->payload[0]);
+}
+
+SHCI_CmdStatus_t SHCI_C2_SetFlashActivityControl(SHCI_C2_SET_FLASH_ACTIVITY_CONTROL_Source_t Source)
+{
+ /**
+ * TL_BLEEVT_CS_BUFFER_SIZE is 15 bytes so it is large enough to hold the 1 byte of command parameter
+ * Buffer is large enough to hold command complete without payload
+ */
+ uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
+ TL_EvtPacket_t *p_rsp;
+
+ p_rsp = (TL_EvtPacket_t *)local_buffer;
+
+ local_buffer[0] = (uint8_t)Source;
+
+ shci_send(SHCI_OPCODE_C2_SET_FLASH_ACTIVITY_CONTROL,
+ 1,
+ local_buffer,
+ p_rsp);
+
+ return (SHCI_CmdStatus_t)(((TL_CcEvt_t *)(p_rsp->evtserial.evt.payload))->payload[0]);
+}
+
+SHCI_CmdStatus_t SHCI_C2_Config(SHCI_C2_CONFIG_Cmd_Param_t *pCmdPacket)
+{
+ /**
+ * Buffer is large enough to hold command complete without payload
+ */
+ uint8_t local_buffer[TL_BLEEVT_CS_BUFFER_SIZE];
+ TL_EvtPacket_t *p_rsp;
+
+ p_rsp = (TL_EvtPacket_t *)local_buffer;
+
+ shci_send(SHCI_OPCODE_C2_CONFIG,
+ sizeof(SHCI_C2_CONFIG_Cmd_Param_t),
+ (uint8_t *)pCmdPacket,
+ p_rsp);
+
+ return (SHCI_CmdStatus_t)(((TL_CcEvt_t *)(p_rsp->evtserial.evt.payload))->payload[0]);
+}
+
+
+/**
+ * Local System COMMAND
+ * These commands are NOT sent to the CPU2
+ */
+
+SHCI_CmdStatus_t SHCI_GetWirelessFwInfo(WirelessFwInfo_t *pWirelessInfo)
+{
+ uint32_t ipccdba = 0;
+ MB_RefTable_t *p_RefTable = NULL;
+ uint32_t version = 0;
+ uint32_t memorySize = 0;
+ uint32_t infoStack = 0;
+
+ ipccdba = READ_BIT(FLASH->IPCCBR, FLASH_IPCCBR_IPCCDBA);
+ p_RefTable = (MB_RefTable_t *)((ipccdba << 2) + SRAM2A_BASE);
+
+ /**
+ * Retrieve the WirelessFwInfoTable
+ * This table is stored in RAM at startup during the TL (transport layer) initialization
+ */
+ version = p_RefTable->p_device_info_table->WirelessFwInfoTable.Version;
+ pWirelessInfo->VersionMajor = ((version & INFO_VERSION_MAJOR_MASK) >> INFO_VERSION_MAJOR_OFFSET);
+ pWirelessInfo->VersionMinor = ((version & INFO_VERSION_MINOR_MASK) >> INFO_VERSION_MINOR_OFFSET);
+ pWirelessInfo->VersionSub = ((version & INFO_VERSION_SUB_MASK) >> INFO_VERSION_SUB_OFFSET);
+ pWirelessInfo->VersionBranch = ((version & INFO_VERSION_BRANCH_MASK) >> INFO_VERSION_BRANCH_OFFSET);
+ pWirelessInfo->VersionReleaseType = ((version & INFO_VERSION_TYPE_MASK) >> INFO_VERSION_TYPE_OFFSET);
+
+ memorySize = p_RefTable->p_device_info_table->WirelessFwInfoTable.MemorySize;
+ pWirelessInfo->MemorySizeSram2B = ((memorySize & INFO_SIZE_SRAM2B_MASK) >> INFO_SIZE_SRAM2B_OFFSET);
+ pWirelessInfo->MemorySizeSram2A = ((memorySize & INFO_SIZE_SRAM2A_MASK) >> INFO_SIZE_SRAM2A_OFFSET);
+ pWirelessInfo->MemorySizeSram1 = ((memorySize & INFO_SIZE_SRAM1_MASK) >> INFO_SIZE_SRAM1_OFFSET);
+ pWirelessInfo->MemorySizeFlash = ((memorySize & INFO_SIZE_FLASH_MASK) >> INFO_SIZE_FLASH_OFFSET);
+
+ infoStack = p_RefTable->p_device_info_table->WirelessFwInfoTable.InfoStack;
+ pWirelessInfo->StackType = ((infoStack & INFO_STACK_TYPE_MASK) >> INFO_STACK_TYPE_OFFSET);
+
+ /**
+ * Retrieve the FusInfoTable
+ * This table is stored in RAM at startup during the TL (transport layer) initialization
+ */
+ version = p_RefTable->p_device_info_table->FusInfoTable.Version;
+ pWirelessInfo->FusVersionMajor = ((version & INFO_VERSION_MAJOR_MASK) >> INFO_VERSION_MAJOR_OFFSET);
+ pWirelessInfo->FusVersionMinor = ((version & INFO_VERSION_MINOR_MASK) >> INFO_VERSION_MINOR_OFFSET);
+ pWirelessInfo->FusVersionSub = ((version & INFO_VERSION_SUB_MASK) >> INFO_VERSION_SUB_OFFSET);
+
+ memorySize = p_RefTable->p_device_info_table->FusInfoTable.MemorySize;
+ pWirelessInfo->FusMemorySizeSram2B = ((memorySize & INFO_SIZE_SRAM2B_MASK) >> INFO_SIZE_SRAM2B_OFFSET);
+ pWirelessInfo->FusMemorySizeSram2A = ((memorySize & INFO_SIZE_SRAM2A_MASK) >> INFO_SIZE_SRAM2A_OFFSET);
+ pWirelessInfo->FusMemorySizeFlash = ((memorySize & INFO_SIZE_FLASH_MASK) >> INFO_SIZE_FLASH_OFFSET);
+
+ return (SHCI_Success);
+}
+#endif /* STM32WBxx */
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/src/utility/STM32Cube_FW/shci.h b/src/utility/STM32Cube_FW/shci.h
new file mode 100644
index 00000000..35227c76
--- /dev/null
+++ b/src/utility/STM32Cube_FW/shci.h
@@ -0,0 +1,888 @@
+/**
+ ******************************************************************************
+ * @file shci.h
+ * @author MCD Application Team
+ * @brief HCI command for the system channel
+ ******************************************************************************
+ * @attention
+ *
+ * © Copyright (c) 2019 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __SHCI_H
+#define __SHCI_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "mbox_def.h" /* Requested to expose the MB_WirelessFwInfoTable_t structure */
+
+/* Exported types ------------------------------------------------------------*/
+
+/* SYSTEM EVENT */
+typedef enum {
+ WIRELESS_FW_RUNNING = 0x00,
+ RSS_FW_RUNNING = 0x01,
+} SHCI_SysEvt_Ready_Rsp_t;
+
+/* ERROR CODES
+ *
+ * These error codes are detected on M0 side and are send back to the M4 via a system
+ * notification message. It is up to the application running on M4 to manage these errors
+ *
+ * These errors can be generated by all layers (low level driver, stack, framework infrastructure, etc..)
+ */
+typedef enum {
+ ERR_BLE_INIT = 0,
+ ERR_THREAD_LLD_FATAL_ERROR = 125, /* The LLD driver used on 802_15_4 detected a fatal error */
+ ERR_THREAD_UNKNOWN_CMD = 126, /* The command send by the M4 to control the Thread stack is unknown */
+} SCHI_SystemErrCode_t;
+
+#define SHCI_EVTCODE ( 0xFF )
+#define SHCI_SUB_EVT_CODE_BASE ( 0x9200 )
+
+/**
+ * THE ORDER SHALL NOT BE CHANGED TO GUARANTEE COMPATIBILITY WITH THE CPU1 DEFINITION
+ */
+typedef enum {
+ SHCI_SUB_EVT_CODE_READY = SHCI_SUB_EVT_CODE_BASE,
+ SHCI_SUB_EVT_ERROR_NOTIF,
+ SHCI_SUB_EVT_BLE_NVM_RAM_UPDATE,
+ SHCI_SUB_EVT_OT_NVM_RAM_UPDATE,
+ SHCI_SUB_EVT_NVM_START_WRITE,
+ SHCI_SUB_EVT_NVM_END_WRITE,
+ SHCI_SUB_EVT_NVM_START_ERASE,
+ SHCI_SUB_EVT_NVM_END_ERASE,
+} SHCI_SUB_EVT_CODE_t;
+
+/**
+ * SHCI_SUB_EVT_CODE_READY
+ * This notifies the CPU1 that the CPU2 is now ready to receive commands
+ * It reports as well which firmware is running on CPU2 : The wireless stack of the FUS (previously named RSS)
+ */
+typedef PACKED_STRUCT{
+ SHCI_SysEvt_Ready_Rsp_t sysevt_ready_rsp;
+} SHCI_C2_Ready_Evt_t;
+
+/**
+ * SHCI_SUB_EVT_ERROR_NOTIF
+ * This reports to the CPU1 some error form the CPU2
+ */
+typedef PACKED_STRUCT{
+ SCHI_SystemErrCode_t errorCode;
+} SHCI_C2_ErrorNotif_Evt_t;
+
+/**
+ * SHCI_SUB_EVT_BLE_NVM_RAM_UPDATE
+ * This notifies the CPU1 which part of the BLE NVM RAM has been updated so that only the modified
+ * section could be written in Flash/NVM
+ * StartAddress : Start address of the section that has been modified
+ * Size : Size (in bytes) of the section that has been modified
+ */
+typedef PACKED_STRUCT{
+ uint32_t StartAddress;
+ uint32_t Size;
+} SHCI_C2_BleNvmRamUpdate_Evt_t;
+
+/**
+ * SHCI_SUB_EVT_OT_NVM_RAM_UPDATE
+ * This notifies the CPU1 which part of the 'OT NVM RAM' has been updated so that only the modified
+ * section could be written in Flash/NVM
+ * StartAddress : Start address of the section that has been modified
+ * Size : Size (in bytes) of the section that has been modified
+ */
+typedef PACKED_STRUCT{
+ uint32_t StartAddress;
+ uint32_t Size;
+} SHCI_C2_OtNvmRamUpdate_Evt_t;
+
+/**
+ * SHCI_SUB_EVT_NVM_START_WRITE
+ * This notifies the CPU1 that the CPU2 has started a write procedure in Flash
+ * NumberOfWords : The number of 64bits data the CPU2 needs to write in Flash.
+ * For each 64bits data, the algorithm as described in AN5289 is executed.
+ * When this number is reported to 0, it means the Number of 64bits to be written
+ * was unknown when the procedure has started.
+ * When all data are written, the SHCI_SUB_EVT_NVM_END_WRITE event is reported
+ */
+typedef PACKED_STRUCT{
+ uint32_t NumberOfWords;
+} SHCI_C2_NvmStartWrite_Evt_t;
+
+/**
+ * SHCI_SUB_EVT_NVM_END_WRITE
+ * This notifies the CPU1 that the CPU2 has written all expected data in Flash
+ */
+
+/**
+ * SHCI_SUB_EVT_NVM_START_ERASE
+ * This notifies the CPU1 that the CPU2 has started a erase procedure in Flash
+ * NumberOfSectors : The number of sectors the CPU2 needs to erase in Flash.
+ * For each sector, the algorithm as described in AN5289 is executed.
+ * When this number is reported to 0, it means the Number of sectors to be erased
+ * was unknown when the procedure has started.
+ * When all sectors are erased, the SHCI_SUB_EVT_NVM_END_ERASE event is reported
+ */
+typedef PACKED_STRUCT{
+ uint32_t NumberOfSectors;
+} SHCI_C2_NvmStartErase_Evt_t;
+
+/**
+ * SHCI_SUB_EVT_NVM_END_ERASE
+ * This notifies the CPU1 that the CPU2 has erased all expected flash sectors
+ */
+
+/* SYSTEM COMMAND */
+typedef PACKED_STRUCT {
+ uint32_t MetaData[3];
+} SHCI_Header_t;
+
+typedef enum {
+ SHCI_Success = 0x00,
+ SHCI_UNKNOWN_CMD = 0x01,
+ SHCI_ERR_UNSUPPORTED_FEATURE = 0x11,
+ SHCI_ERR_INVALID_HCI_CMD_PARAMS = 0x12,
+ SHCI_FUS_CMD_NOT_SUPPORTED = 0xFF,
+} SHCI_CmdStatus_t;
+
+typedef enum {
+ SHCI_8BITS = 0x01,
+ SHCI_16BITS = 0x02,
+ SHCI_32BITS = 0x04,
+} SHCI_Busw_t;
+
+#define SHCI_OGF ( 0x3F )
+#define SHCI_OCF_BASE ( 0x50 )
+
+/**
+ * THE ORDER SHALL NOT BE CHANGED TO GUARANTEE COMPATIBILITY WITH THE CPU2 DEFINITION
+ */
+typedef enum {
+ SHCI_OCF_C2_RESERVED1 = SHCI_OCF_BASE,
+ SHCI_OCF_C2_RESERVED2,
+ SHCI_OCF_C2_FUS_GET_STATE,
+ SHCI_OCF_C2_FUS_RESERVED1,
+ SHCI_OCF_C2_FUS_FW_UPGRADE,
+ SHCI_OCF_C2_FUS_FW_DELETE,
+ SHCI_OCF_C2_FUS_UPDATE_AUTH_KEY,
+ SHCI_OCF_C2_FUS_LOCK_AUTH_KEY,
+ SHCI_OCF_C2_FUS_STORE_USR_KEY,
+ SHCI_OCF_C2_FUS_LOAD_USR_KEY,
+ SHCI_OCF_C2_FUS_START_WS,
+ SHCI_OCF_C2_FUS_RESERVED2,
+ SHCI_OCF_C2_FUS_RESERVED3,
+ SHCI_OCF_C2_FUS_LOCK_USR_KEY,
+ SHCI_OCF_C2_FUS_RESERVED5,
+ SHCI_OCF_C2_FUS_RESERVED6,
+ SHCI_OCF_C2_FUS_RESERVED7,
+ SHCI_OCF_C2_FUS_RESERVED8,
+ SHCI_OCF_C2_FUS_RESERVED9,
+ SHCI_OCF_C2_FUS_RESERVED10,
+ SHCI_OCF_C2_FUS_RESERVED11,
+ SHCI_OCF_C2_FUS_RESERVED12,
+ SHCI_OCF_C2_BLE_INIT,
+ SHCI_OCF_C2_THREAD_INIT,
+ SHCI_OCF_C2_DEBUG_INIT,
+ SHCI_OCF_C2_FLASH_ERASE_ACTIVITY,
+ SHCI_OCF_C2_CONCURRENT_SET_MODE,
+ SHCI_OCF_C2_FLASH_STORE_DATA,
+ SHCI_OCF_C2_FLASH_ERASE_DATA,
+ SHCI_OCF_C2_RADIO_ALLOW_LOW_POWER,
+ SHCI_OCF_C2_REINIT,
+ SHCI_OCF_C2_LLD_TESTS_INIT,
+ SHCI_OCF_C2_EXTPA_CONFIG,
+ SHCI_OCF_C2_SET_FLASH_ACTIVITY_CONTROL,
+ SHCI_OCF_C2_LLD_BLE_INIT,
+ SHCI_OCF_C2_CONFIG,
+} SHCI_OCF_t;
+
+#define SHCI_OPCODE_C2_FUS_GET_STATE (( SHCI_OGF << 10) + SHCI_OCF_C2_FUS_GET_STATE)
+/** No command parameters */
+/** Response parameters*/
+typedef enum {
+ FUS_STATE_NO_ERROR = 0x00,
+ FUS_STATE_IMG_NOT_FOUND = 0x01,
+ FUS_STATE_IMG_CORRUPT = 0x02,
+ FUS_STATE_IMG_NOT_AUTHENTIC = 0x03,
+ FUS_STATE_IMG_NOT_ENOUGH_SPACE = 0x04,
+ FUS_STATE_ERR_UNKNOWN = 0xFF,
+} SHCI_FUS_GetState_ErrorCode_t;
+
+#define SHCI_OPCODE_C2_FUS_RESERVED1 (( SHCI_OGF << 10) + SHCI_OCF_C2_FUS_RESERVED1)
+/** No command parameters */
+/** No response parameters*/
+
+#define SHCI_OPCODE_C2_FUS_FW_UPGRADE (( SHCI_OGF << 10) + SHCI_OCF_C2_FUS_FW_UPGRADE)
+/** No structure for command parameters */
+/** No response parameters*/
+
+#define SHCI_OPCODE_C2_FUS_FW_DELETE (( SHCI_OGF << 10) + SHCI_OCF_C2_FUS_FW_DELETE)
+/** No command parameters */
+/** No response parameters*/
+
+#define SHCI_OPCODE_C2_FUS_UPDATE_AUTH_KEY (( SHCI_OGF << 10) + SHCI_OCF_C2_FUS_UPDATE_AUTH_KEY)
+typedef PACKED_STRUCT {
+ uint8_t KeySize;
+ uint8_t KeyData[64];
+} SHCI_C2_FUS_UpdateAuthKey_Cmd_Param_t;
+
+/** No response parameters*/
+
+#define SHCI_OPCODE_C2_FUS_LOCK_AUTH_KEY (( SHCI_OGF << 10) + SHCI_OCF_C2_FUS_LOCK_AUTH_KEY)
+/** No command parameters */
+/** No response parameters*/
+
+#define SHCI_OPCODE_C2_FUS_STORE_USR_KEY (( SHCI_OGF << 10) + SHCI_OCF_C2_FUS_STORE_USR_KEY)
+/** Command parameters */
+/* List of supported key type */
+enum {
+ KEYTYPE_NONE = 0x00,
+ KEYTYPE_SIMPLE = 0x01,
+ KEYTYPE_MASTER = 0x02,
+ KEYTYPE_ENCRYPTED = 0x03,
+};
+
+/* List of supported key size */
+enum {
+ KEYSIZE_16 = 16,
+ KEYSIZE_32 = 32,
+};
+
+typedef PACKED_STRUCT{
+ uint8_t KeyType;
+ uint8_t KeySize;
+ uint8_t KeyData[32 + 12];
+} SHCI_C2_FUS_StoreUsrKey_Cmd_Param_t;
+
+/** Response parameters*/
+/** It responds a 1 byte value holding the index given for the stored key */
+
+#define SHCI_OPCODE_C2_FUS_LOAD_USR_KEY (( SHCI_OGF << 10) + SHCI_OCF_C2_FUS_LOAD_USR_KEY)
+/** Command parameters */
+/** 1 byte holding the key index value */
+
+/** No response parameters*/
+
+#define SHCI_OPCODE_C2_FUS_START_WS (( SHCI_OGF << 10) + SHCI_OCF_C2_FUS_START_WS)
+/** No command parameters */
+/** No response parameters*/
+
+#define SHCI_OPCODE_C2_FUS_RESERVED2 (( SHCI_OGF << 10) + SHCI_OCF_C2_FUS_RESERVED2)
+/** No command parameters */
+/** No response parameters*/
+
+#define SHCI_OPCODE_C2_FUS_RESERVED3 (( SHCI_OGF << 10) + SHCI_OCF_C2_FUS_RESERVED3)
+/** No command parameters */
+/** No response parameters*/
+
+#define SHCI_OPCODE_C2_FUS_LOCK_USR_KEY (( SHCI_OGF << 10) + SHCI_OCF_C2_FUS_LOCK_USR_KEY)
+/** Command parameters */
+/** 1 byte holding the key index value */
+
+/** No response parameters*/
+
+#define SHCI_OPCODE_C2_FUS_RESERVED5 (( SHCI_OGF << 10) + SHCI_OCF_C2_FUS_RESERVED5)
+/** No command parameters */
+/** No response parameters*/
+
+#define SHCI_OPCODE_C2_FUS_RESERVED6 (( SHCI_OGF << 10) + SHCI_OCF_C2_FUS_RESERVED6)
+/** No command parameters */
+/** No response parameters*/
+
+#define SHCI_OPCODE_C2_FUS_RESERVED7 (( SHCI_OGF << 10) + SHCI_OCF_C2_FUS_RESERVED7)
+/** No command parameters */
+/** No response parameters*/
+
+#define SHCI_OPCODE_C2_FUS_RESERVED8 (( SHCI_OGF << 10) + SHCI_OCF_C2_FUS_RESERVED8)
+/** No command parameters */
+/** No response parameters*/
+
+#define SHCI_OPCODE_C2_FUS_RESERVED9 (( SHCI_OGF << 10) + SHCI_OCF_C2_FUS_RESERVED9)
+/** No command parameters */
+/** No response parameters*/
+
+#define SHCI_OPCODE_C2_FUS_RESERVED10 (( SHCI_OGF << 10) + SHCI_OCF_C2_FUS_RESERVED10)
+/** No command parameters */
+/** No response parameters*/
+
+#define SHCI_OPCODE_C2_FUS_RESERVED11 (( SHCI_OGF << 10) + SHCI_OCF_C2_FUS_RESERVED11)
+/** No command parameters */
+/** No response parameters*/
+
+#define SHCI_OPCODE_C2_FUS_RESERVED12 (( SHCI_OGF << 10) + SHCI_OCF_C2_FUS_RESERVED12)
+/** No command parameters */
+/** No response parameters*/
+
+#define SHCI_OPCODE_C2_BLE_INIT (( SHCI_OGF << 10) + SHCI_OCF_C2_BLE_INIT)
+/** THE ORDER SHALL NOT BE CHANGED */
+typedef PACKED_STRUCT{
+ uint8_t *pBleBufferAddress; /**< NOT USED CURRENTLY */
+ uint32_t BleBufferSize; /**< Size of the Buffer allocated in pBleBufferAddress */
+ uint16_t NumAttrRecord;
+ uint16_t NumAttrServ;
+ uint16_t AttrValueArrSize;
+ uint8_t NumOfLinks;
+ uint8_t ExtendedPacketLengthEnable;
+ uint8_t PrWriteListSize;
+ uint8_t MblockCount;
+ uint16_t AttMtu;
+ uint16_t SlaveSca;
+ uint8_t MasterSca;
+ uint8_t LsSource;
+ uint32_t MaxConnEventLength;
+ uint16_t HsStartupTime;
+ uint8_t ViterbiEnable;
+ uint8_t LlOnly;
+ uint8_t HwVersion;
+} SHCI_C2_Ble_Init_Cmd_Param_t;
+
+typedef PACKED_STRUCT{
+ SHCI_Header_t Header; /** Does not need to be initialized by the user */
+ SHCI_C2_Ble_Init_Cmd_Param_t Param;
+} SHCI_C2_Ble_Init_Cmd_Packet_t;
+
+/** No response parameters*/
+
+#define SHCI_OPCODE_C2_THREAD_INIT (( SHCI_OGF << 10) + SHCI_OCF_C2_THREAD_INIT)
+/** No command parameters */
+/** No response parameters*/
+
+#define SHCI_OPCODE_C2_DEBUG_INIT (( SHCI_OGF << 10) + SHCI_OCF_C2_DEBUG_INIT)
+/** Command parameters */
+typedef PACKED_STRUCT {
+ uint8_t thread_config;
+ uint8_t ble_config;
+} SHCI_C2_DEBUG_TracesConfig_t;
+
+typedef PACKED_STRUCT {
+ uint8_t ble_dtb_cfg;
+ uint8_t reserved[3];
+} SHCI_C2_DEBUG_GeneralConfig_t;
+
+typedef PACKED_STRUCT{
+ uint8_t *pGpioConfig;
+ uint8_t *pTracesConfig;
+ uint8_t *pGeneralConfig;
+ uint8_t GpioConfigSize;
+ uint8_t TracesConfigSize;
+ uint8_t GeneralConfigSize;
+} SHCI_C2_DEBUG_init_Cmd_Param_t;
+
+typedef PACKED_STRUCT{
+ SHCI_Header_t Header; /** Does not need to be initialized by the user */
+ SHCI_C2_DEBUG_init_Cmd_Param_t Param;
+} SHCI_C2_DEBUG_Init_Cmd_Packet_t;
+/** No response parameters*/
+
+#define SHCI_OPCODE_C2_FLASH_ERASE_ACTIVITY (( SHCI_OGF << 10) + SHCI_OCF_C2_FLASH_ERASE_ACTIVITY)
+/** Command parameters */
+typedef enum {
+ ERASE_ACTIVITY_OFF = 0x00,
+ ERASE_ACTIVITY_ON = 0x01,
+} SHCI_EraseActivity_t;
+
+/** No response parameters*/
+
+#define SHCI_OPCODE_C2_CONCURRENT_SET_MODE (( SHCI_OGF << 10) + SHCI_OCF_C2_CONCURRENT_SET_MODE)
+/** command parameters */
+typedef enum {
+ BLE_ENABLE,
+ THREAD_ENABLE,
+} SHCI_C2_CONCURRENT_Mode_Param_t;
+/** No response parameters*/
+
+#define SHCI_OPCODE_C2_FLASH_STORE_DATA (( SHCI_OGF << 10) + SHCI_OCF_C2_FLASH_STORE_DATA)
+#define SHCI_OPCODE_C2_FLASH_ERASE_DATA (( SHCI_OGF << 10) + SHCI_OCF_C2_FLASH_ERASE_DATA)
+/** command parameters */
+typedef enum {
+ BLE_IP,
+ THREAD_IP,
+} SHCI_C2_FLASH_Ip_t;
+/** No response parameters*/
+
+#define SHCI_OPCODE_C2_RADIO_ALLOW_LOW_POWER (( SHCI_OGF << 10) + SHCI_OCF_C2_RADIO_ALLOW_LOW_POWER)
+
+#define SHCI_OPCODE_C2_REINIT (( SHCI_OGF << 10) + SHCI_OCF_C2_REINIT)
+
+#define SHCI_OPCODE_C2_LLD_TESTS_INIT (( SHCI_OGF << 10) + SHCI_OCF_C2_LLD_TESTS_INIT)
+
+#define SHCI_OPCODE_C2_LLD_BLE_INIT (( SHCI_OGF << 10) + SHCI_OCF_C2_LLD_BLE_INIT)
+
+#define SHCI_OPCODE_C2_EXTPA_CONFIG (( SHCI_OGF << 10) + SHCI_OCF_C2_EXTPA_CONFIG)
+/** Command parameters */
+enum {
+ EXT_PA_ENABLED_LOW,
+ EXT_PA_ENABLED_HIGH,
+}/* gpio_polarity */;
+
+enum {
+ EXT_PA_DISABLED,
+ EXT_PA_ENABLED,
+}/* gpio_status */;
+
+typedef PACKED_STRUCT{
+ uint32_t gpio_port;
+ uint16_t gpio_pin_number;
+ uint8_t gpio_polarity;
+ uint8_t gpio_status;
+} SHCI_C2_EXTPA_CONFIG_Cmd_Param_t;
+
+/** No response parameters*/
+
+#define SHCI_OPCODE_C2_SET_FLASH_ACTIVITY_CONTROL (( SHCI_OGF << 10) + SHCI_OCF_C2_SET_FLASH_ACTIVITY_CONTROL)
+/** Command parameters */
+typedef enum {
+ FLASH_ACTIVITY_CONTROL_PES,
+ FLASH_ACTIVITY_CONTROL_SEM7,
+} SHCI_C2_SET_FLASH_ACTIVITY_CONTROL_Source_t;
+
+/** No response parameters*/
+
+#define SHCI_OPCODE_C2_CONFIG (( SHCI_OGF << 10) + SHCI_OCF_C2_CONFIG)
+/** Command parameters */
+typedef PACKED_STRUCT{
+ uint8_t PayloadCmdSize;
+ uint8_t Config1;
+ uint8_t EvtMask1;
+ uint8_t Spare1;
+ uint32_t BleNvmRamAddress;
+ uint32_t ThreadNvmRamAddress;
+} SHCI_C2_CONFIG_Cmd_Param_t;
+
+/**
+ * PayloadCmdSize
+ * Value that shall be used
+ */
+#define SHCI_C2_CONFIG_PAYLOAD_CMD_SIZE (sizeof(SHCI_C2_CONFIG_Cmd_Param_t) - 1)
+
+/**
+ * Config1
+ * Each definition below may be added together to build the Config1 value
+ * WARNING : Only one definition per bit shall be added to build the Config1 value
+ */
+#define SHCI_C2_CONFIG_CONFIG1_BIT0_BLE_NVM_DATA_TO_INTERNAL_FLASH (0<<0)
+#define SHCI_C2_CONFIG_CONFIG1_BIT0_BLE_NVM_DATA_TO_SRAM (1<<0)
+#define SHCI_C2_CONFIG_CONFIG1_BIT1_THREAD_NVM_DATA_TO_INTERNAL_FLASH (0<<1)
+#define SHCI_C2_CONFIG_CONFIG1_BIT1_THREAD_NVM_DATA_TO_SRAM (1<<1)
+
+/**
+ * EvtMask1
+ * Each definition below may be added together to build the EvtMask1 value
+ */
+#define SHCI_C2_CONFIG_EVTMASK1_BIT0_ERROR_NOTIF_ENABLE (1<<0)
+#define SHCI_C2_CONFIG_EVTMASK1_BIT1_BLE_NVM_RAM_UPDATE_ENABLE (1<<1)
+#define SHCI_C2_CONFIG_EVTMASK1_BIT2_OT_NVM_RAM_UPDATE_ENABLE (1<<2)
+#define SHCI_C2_CONFIG_EVTMASK1_BIT3_NVM_START_WRITE_ENABLE (1<<3)
+#define SHCI_C2_CONFIG_EVTMASK1_BIT4_NVM_END_WRITE_ENABLE (1<<4)
+#define SHCI_C2_CONFIG_EVTMASK1_BIT5_NVM_START_ERASE_ENABLE (1<<5)
+#define SHCI_C2_CONFIG_EVTMASK1_BIT6_NVM_END_ERASE_ENABLE (1<<6)
+
+/**
+ * BleNvmRamAddress
+ * The buffer shall have a size of BLE_NVM_SRAM_SIZE number of 32bits
+ * The buffer shall be allocated in SRAM2
+ */
+#define BLE_NVM_SRAM_SIZE (507)
+
+/**
+ * ThreadNvmRamAddress
+ * The buffer shall have a size of THREAD_NVM_SRAM_SIZE number of 32bits
+ * The buffer shall be allocated in SRAM2
+ */
+#define THREAD_NVM_SRAM_SIZE (1016)
+
+
+/** No response parameters*/
+
+/* Exported type --------------------------------------------------------*/
+
+typedef MB_WirelessFwInfoTable_t SHCI_WirelessFwInfoTable_t;
+
+/*
+ * At startup, the information relative to the wireless binary are stored in RAM through a structure defined by
+ * SHCI_WirelessFwInfoTable_t.This structure contains 4 fields (Version,MemorySize, Stack_info and a reserved part)
+ * each of those coded on 32 bits as shown on the table below:
+ *
+ *
+ * |7 |6 |5 |4 |3 |2 |1 |0 |7 |6 |5 |4 |3 |2 |1 |0 |7 |6 |5 |4 |3 |2 |1 |0 |7 |6 |5 |4 |3 |2 |1 |0 |
+ * -------------------------------------------------------------------------------------------------
+ * Version | Major version | Minor version | Sub version | Branch |Release Type|
+ * -------------------------------------------------------------------------------------------------
+ * MemorySize | SRAM2B (kB) | SRAM2A (kB) | SRAM1 (kB) | FLASH (4kb) |
+ * -------------------------------------------------------------------------------------------------
+ * Info stack | Reserved | Reserved | Reserved | Type (MAC,Thread,BLE) |
+ * -------------------------------------------------------------------------------------------------
+ * Reserved | Reserved | Reserved | Reserved | Reserved |
+ * -------------------------------------------------------------------------------------------------
+ *
+ */
+
+/* Field Version */
+#define INFO_VERSION_MAJOR_OFFSET 24
+#define INFO_VERSION_MAJOR_MASK 0xff000000
+#define INFO_VERSION_MINOR_OFFSET 16
+#define INFO_VERSION_MINOR_MASK 0x00ff0000
+#define INFO_VERSION_SUB_OFFSET 8
+#define INFO_VERSION_SUB_MASK 0x0000ff00
+#define INFO_VERSION_BRANCH_OFFSET 4
+#define INFO_VERSION_BRANCH_MASK 0x0000000f0
+#define INFO_VERSION_TYPE_OFFSET 0
+#define INFO_VERSION_TYPE_MASK 0x00000000f
+
+#define INFO_VERSION_TYPE_RELEASE 1
+
+/* Field Memory */
+#define INFO_SIZE_SRAM2B_OFFSET 24
+#define INFO_SIZE_SRAM2B_MASK 0xff000000
+#define INFO_SIZE_SRAM2A_OFFSET 16
+#define INFO_SIZE_SRAM2A_MASK 0x00ff0000
+#define INFO_SIZE_SRAM1_OFFSET 8
+#define INFO_SIZE_SRAM1_MASK 0x0000ff00
+#define INFO_SIZE_FLASH_OFFSET 0
+#define INFO_SIZE_FLASH_MASK 0x000000ff
+
+/* Field stack information */
+#define INFO_STACK_TYPE_OFFSET 0
+#define INFO_STACK_TYPE_MASK 0x000000ff
+#define INFO_STACK_TYPE_NONE 0
+
+#define INFO_STACK_TYPE_BLE_STANDARD 0x01
+#define INFO_STACK_TYPE_BLE_HCI 0x02
+#define INFO_STACK_TYPE_BLE_LIGHT 0x03
+#define INFO_STACK_TYPE_THREAD_FTD 0x10
+#define INFO_STACK_TYPE_THREAD_MTD 0x11
+#define INFO_STACK_TYPE_BLE_THREAD_FTD_STATIC 0x50
+#define INFO_STACK_TYPE_BLE_THREAD_FTD_DYAMIC 0x51
+#define INFO_STACK_TYPE_BLE_PHY_VALID 0x62
+#define INFO_STACK_TYPE_BLE_LLD_TESTS 0x63
+#define INFO_STACK_TYPE_BLE_RLV 0x64
+#define INFO_STACK_TYPE_RLV 0x80
+
+typedef struct {
+ /**
+ * Wireless Info
+ */
+ uint8_t VersionMajor;
+ uint8_t VersionMinor;
+ uint8_t VersionSub;
+ uint8_t VersionBranch;
+ uint8_t VersionReleaseType;
+ uint8_t MemorySizeSram2B; /*< Multiple of 1K */
+ uint8_t MemorySizeSram2A; /*< Multiple of 1K */
+ uint8_t MemorySizeSram1; /*< Multiple of 1K */
+ uint8_t MemorySizeFlash; /*< Multiple of 4K */
+ uint8_t StackType;
+ /**
+ * Fus Info
+ */
+ uint8_t FusVersionMajor;
+ uint8_t FusVersionMinor;
+ uint8_t FusVersionSub;
+ uint8_t FusMemorySizeSram2B; /*< Multiple of 1K */
+ uint8_t FusMemorySizeSram2A; /*< Multiple of 1K */
+ uint8_t FusMemorySizeFlash; /*< Multiple of 4K */
+} WirelessFwInfo_t;
+
+
+/* Exported functions ------------------------------------------------------- */
+
+/**
+ * For all SHCI_C2_FUS_xxx() command:
+ * When the wireless FW is running on the CPU2, the command returns SHCI_FUS_CMD_NOT_SUPPORTED
+ * When any FUS command is sent after the SHCI_FUS_CMD_NOT_SUPPORTED has been received,
+ * the CPU2 switches on the RSS ( This reboots automatically the device )
+ */
+/**
+* SHCI_C2_FUS_GetState
+* @brief Read the FUS State
+* If the user is not interested by the Error code response, a null value may
+* be passed as parameter
+*
+* @param p_rsp : return the error code when the FUS State Value = 0xFF
+* @retval FUS State Values
+*/
+uint8_t SHCI_C2_FUS_GetState(SHCI_FUS_GetState_ErrorCode_t *p_rsp);
+
+/**
+* SHCI_C2_FUS_FwUpgrade
+* @brief Request the FUS to install the CPU2 firmware update
+*
+* @param fw_src_add: Address of the firmware image location
+* @param fw_dest_add: Address of the firmware destination
+* @retval Status
+*/
+SHCI_CmdStatus_t SHCI_C2_FUS_FwUpgrade(uint32_t fw_src_add, uint32_t fw_dest_add);
+
+/**
+* SHCI_C2_FUS_FwDelete
+* @brief Delete the wireless stack on CPU2
+*
+* @param None
+* @retval Status
+*/
+SHCI_CmdStatus_t SHCI_C2_FUS_FwDelete(void);
+
+/**
+* SHCI_C2_FUS_UpdateAuthKey
+* @brief Request the FUS to update the authentication key
+*
+* @param pCmdPacket
+* @retval Status
+*/
+SHCI_CmdStatus_t SHCI_C2_FUS_UpdateAuthKey(SHCI_C2_FUS_UpdateAuthKey_Cmd_Param_t *pParam);
+
+/**
+* SHCI_C2_FUS_LockAuthKey
+* @brief Request the FUS to prevent any future update of the authentication key
+*
+* @param None
+* @retval Status
+*/
+SHCI_CmdStatus_t SHCI_C2_FUS_LockAuthKey(void);
+
+/**
+* SHCI_C2_FUS_StoreUsrKey
+* @brief Request the FUS to store the user key
+*
+* @param pParam : command parameter
+* @param p_key_index : Index allocated by the FUS to the stored key
+*
+* @retval Status
+*/
+SHCI_CmdStatus_t SHCI_C2_FUS_StoreUsrKey(SHCI_C2_FUS_StoreUsrKey_Cmd_Param_t *pParam, uint8_t *p_key_index);
+
+/**
+* SHCI_C2_FUS_LoadUsrKey
+* @brief Request the FUS to load the user key into the AES
+*
+* @param key_index : index of the user key to load in AES1
+* @retval Status
+*/
+SHCI_CmdStatus_t SHCI_C2_FUS_LoadUsrKey(uint8_t key_index);
+
+/**
+* SHCI_C2_FUS_StartWs
+* @brief Request the FUS to reboot on the wireless stack
+*
+* @param None
+* @retval Status
+*/
+SHCI_CmdStatus_t SHCI_C2_FUS_StartWs(void);
+
+/**
+* SHCI_C2_FUS_LockUsrKey
+* @brief Request the FUS to lock the user key so that it cannot be updated later on
+*
+* @param key_index : index of the user key to lock
+* @retval Status
+*/
+SHCI_CmdStatus_t SHCI_C2_FUS_LockUsrKey(uint8_t key_index);
+
+/**
+* SHCI_C2_BLE_Init
+* @brief Provides parameters and starts the BLE Stack
+*
+* @param pCmdPacket : Parameters to be provided to the BLE Stack
+* @retval Status
+*/
+SHCI_CmdStatus_t SHCI_C2_BLE_Init(SHCI_C2_Ble_Init_Cmd_Packet_t *pCmdPacket);
+
+/**
+* SHCI_C2_THREAD_Init
+* @brief Starts the THREAD Stack
+*
+* @param None
+* @retval Status
+*/
+SHCI_CmdStatus_t SHCI_C2_THREAD_Init(void);
+
+/**
+* SHCI_C2_LLDTESTS_Init
+* @brief Starts the LLD tests CLI
+*
+* @param param_size : Nb of bytes
+* @param p_param : pointer with data to give from M4 to M0
+* @retval Status
+*/
+SHCI_CmdStatus_t SHCI_C2_LLDTESTS_Init(uint8_t param_size, uint8_t *p_param);
+
+/**
+* SHCI_C2_LLD_BLE_Init
+* @brief Starts the LLD tests CLI
+*
+* @param param_size : Nb of bytes
+* @param p_param : pointer with data to give from M4 to M0
+* @retval Status
+*/
+SHCI_CmdStatus_t SHCI_C2_LLD_BLE_Init(uint8_t param_size, uint8_t *p_param);
+
+/**
+* SHCI_C2_DEBUG_Init
+* @brief Starts the Traces
+*
+* @param None
+* @retval Status
+*/
+SHCI_CmdStatus_t SHCI_C2_DEBUG_Init(SHCI_C2_DEBUG_Init_Cmd_Packet_t *pCmdPacket);
+
+/**
+* SHCI_C2_FLASH_EraseActivity
+* @brief Provides the information of the start and the end of a flash erase window on the CPU1
+*
+* @param erase_activity: Start/End of erase activity
+* @retval Status
+*/
+SHCI_CmdStatus_t SHCI_C2_FLASH_EraseActivity(SHCI_EraseActivity_t erase_activity);
+
+/**
+* SHCI_C2_CONCURRENT_SetMode
+* @brief Enable/Disable Thread on CPU2 (M0+)
+*
+* @param Mode: BLE or Thread enable flag
+* @retval Status
+*/
+SHCI_CmdStatus_t SHCI_C2_CONCURRENT_SetMode(SHCI_C2_CONCURRENT_Mode_Param_t Mode);
+
+/**
+* SHCI_C2_FLASH_StoreData
+* @brief Store Data in Flash
+*
+* @param Ip: BLE or THREAD
+* @retval Status
+*/
+SHCI_CmdStatus_t SHCI_C2_FLASH_StoreData(SHCI_C2_FLASH_Ip_t Ip);
+
+/**
+* SHCI_C2_FLASH_EraseData
+* @brief Erase Data in Flash
+*
+* @param Ip: BLE or THREAD
+* @retval Status
+*/
+SHCI_CmdStatus_t SHCI_C2_FLASH_EraseData(SHCI_C2_FLASH_Ip_t Ip);
+
+/**
+* SHCI_C2_RADIO_AllowLowPower
+* @brief Allow or forbid IP_radio (802_15_4 or BLE) to enter in low power mode.
+*
+* @param Ip: BLE or 802_15_5
+* @param FlagRadioLowPowerOn: True or false
+* @retval Status
+*/
+SHCI_CmdStatus_t SHCI_C2_RADIO_AllowLowPower(SHCI_C2_FLASH_Ip_t Ip, uint8_t FlagRadioLowPowerOn);
+
+/**
+ * SHCI_GetWirelessFwInfo
+ * @brief This function read back the information relative to the wireless binary loaded.
+ * Refer yourself to SHCI_WirelessFwInfoTable_t structure to get the significance
+ * of the different parameters returned.
+ * @param pWirelessInfo : Pointer to WirelessFwInfo_t.
+ *
+ * @retval SHCI_Success
+ */
+SHCI_CmdStatus_t SHCI_GetWirelessFwInfo(WirelessFwInfo_t *pWirelessInfo);
+
+/**
+* SHCI_C2_Reinit
+* @brief This is required to allow the CPU1 to fake a set C2BOOT when it has already been set.
+* In order to fake a C2BOOT, the CPU1 shall :
+* - Send SHCI_C2_Reinit()
+* - call SEV instruction
+* WARNING:
+* This function is intended to be used by the SBSFU
+*
+* @param None
+* @retval Status
+*/
+SHCI_CmdStatus_t SHCI_C2_Reinit(void);
+
+/**
+* SHCI_C2_ExtpaConfig
+* @brief Send the Ext PA configuration
+* When the CPU2 receives the command, it controls the Ext PA as requested by the configuration
+* This configures only which IO is used to enable/disable the ExtPA and the associated polarity
+* This command has no effect on the other IO that is used to control the mode of the Ext PA (Rx/Tx)
+*
+* @param gpio_port: GPIOx where x can be (A..F) to select the GPIO peripheral for STM32WBxx family
+* @param gpio_pin_number: This parameter can be one of GPIO_PIN_x (= LL_GPIO_PIN_x) where x can be (0..15).
+* @param gpio_polarity: This parameter can be either
+* - EXT_PA_ENABLED_LOW: ExtPA is enabled when GPIO is low
+* - EXT_PA_ENABLED_HIGH: ExtPA is enabled when GPIO is high
+* @param gpio_status: This parameter can be either
+* - EXT_PA_DISABLED: Stop driving the ExtPA
+* - EXT_PA_ENABLED: Drive the ExtPA according to radio activity
+* (ON before the Event and OFF at the end of the event)
+* @retval Status
+*/
+SHCI_CmdStatus_t SHCI_C2_ExtpaConfig(uint32_t gpio_port, uint16_t gpio_pin_number, uint8_t gpio_polarity, uint8_t gpio_status);
+
+/**
+* SHCI_C2_SetFlashActivityControl
+* @brief Set the mechanism to be used on CPU2 to prevent the CPU1 to either write or erase in flash
+*
+* @param Source: It can be one of the following list
+* - FLASH_ACTIVITY_CONTROL_PES : The CPU2 set the PES bit to prevent the CPU1 to either read or write in flash
+* - FLASH_ACTIVITY_CONTROL_SEM7 : The CPU2 gets the semaphore 7 to prevent the CPU1 to either read or write in flash.
+* This requires the CPU1 to first get semaphore 7 before erasing or writing the flash.
+*
+* @retval Status
+*/
+SHCI_CmdStatus_t SHCI_C2_SetFlashActivityControl(SHCI_C2_SET_FLASH_ACTIVITY_CONTROL_Source_t Source);
+
+/**
+* SHCI_C2_Config
+* @brief Send the system configuration to the CPU2
+*
+* @param pCmdPacket: address of the buffer holding following parameters
+* uint8_t PayloadCmdSize : Size of the payload - shall be SHCI_C2_CONFIG_PAYLOAD_CMD_SIZE
+* uint8_t Config1 :
+* - bit0 : 0 - BLE NVM Data data are flushed in internal secure flash
+* 1 - BLE NVM Data are written in SRAM cache pointed by BleNvmRamAddress
+* - bit1 : 0 - THREAD NVM Data data are flushed in internal secure flash
+* 1 - THREAD NVM Data are written in SRAM cache pointed by ThreadNvmRamAddress
+* - bit2 to bit7 : Unused, shall be set to 0
+* uint8_t EvtMask1 :
+* When a bit is set to 0, the event is not reported
+* bit0 : Asynchronous Event with Sub Evt Code 0x9201 (= SHCI_SUB_EVT_ERROR_NOTIF)
+* ...
+* bit31 : Asynchronous Event with Sub Evt Code 0x9220
+* uint8_t Spare1 : Unused, shall be set to 0
+* uint32_t BleNvmRamAddress :
+* Only considered when Config1.bit0 = 1
+* When set to 0, data are kept in internal SRAM on CPU2
+* Otherwise, data are copied in the cache pointed by BleNvmRamAddress
+* The size of the buffer shall be BLE_NVM_SRAM_SIZE (number of 32bits)
+* The buffer shall be allocated in SRAM2
+* uint32_t ThreadNvmRamAddress :
+* Only considered when Config1.bit1 = 1
+* When set to 0, data are kept in internal SRAM on CPU2
+* Otherwise, data are copied in the cache pointed by ThreadNvmRamAddress
+* The size of the buffer shall be THREAD_NVM_SRAM_SIZE (number of 32bits)
+* The buffer shall be allocated in SRAM2
+*
+* Please check macro definition to be used for this function
+* They are defined in this file next to the definition of SHCI_OPCODE_C2_CONFIG
+*
+* @retval Status
+*/
+SHCI_CmdStatus_t SHCI_C2_Config(SHCI_C2_CONFIG_Cmd_Param_t *pCmdPacket);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__SHCI_H */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/src/utility/STM32Cube_FW/shci_tl.c b/src/utility/STM32Cube_FW/shci_tl.c
new file mode 100644
index 00000000..1ab15b47
--- /dev/null
+++ b/src/utility/STM32Cube_FW/shci_tl.c
@@ -0,0 +1,344 @@
+/**
+ ******************************************************************************
+ * @file shci.c
+ * @author MCD Application Team
+ * @brief System HCI command implementation
+ ******************************************************************************
+ * @attention
+ *
+ * © Copyright (c) 2019 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+#if defined(STM32WBxx)
+/* Includes ------------------------------------------------------------------*/
+#include "stm32_wpan_common.h"
+
+#include "stm_list.h"
+#include "shci_tl.h"
+#include "stm32_def.h"
+
+/**
+ * These traces are not yet supported in an usual way in the delivery package
+ * They can enabled by adding the definition of TL_SHCI_CMD_DBG_EN and/or TL_SHCI_EVT_DBG_EN in the preprocessor option in the IDE
+ */
+#if ( (TL_SHCI_CMD_DBG_EN != 0) || (TL_SHCI_EVT_DBG_EN != 0) )
+ #include "app_conf.h"
+ #include "dbg_trace.h"
+#endif
+
+#if (TL_SHCI_CMD_DBG_EN != 0)
+ #define TL_SHCI_CMD_DBG_MSG PRINT_MESG_DBG
+ #define TL_SHCI_CMD_DBG_BUF PRINT_LOG_BUFF_DBG
+#else
+ #define TL_SHCI_CMD_DBG_MSG(...)
+ #define TL_SHCI_CMD_DBG_BUF(...)
+#endif
+
+#if (TL_SHCI_EVT_DBG_EN != 0)
+ #define TL_SHCI_EVT_DBG_MSG PRINT_MESG_DBG
+ #define TL_SHCI_EVT_DBG_BUF PRINT_LOG_BUFF_DBG
+#else
+ #define TL_SHCI_EVT_DBG_MSG(...)
+ #define TL_SHCI_EVT_DBG_BUF(...)
+#endif
+
+/* Private typedef -----------------------------------------------------------*/
+typedef enum {
+ SHCI_TL_CMD_RESP_RELEASE,
+ SHCI_TL_CMD_RESP_WAIT,
+} SHCI_TL_CmdRespStatus_t;
+
+/* Private defines -----------------------------------------------------------*/
+/**
+ * The default System HCI layer timeout is set to 33s
+ */
+#define SHCI_TL_DEFAULT_TIMEOUT (33000)
+
+/* Private macros ------------------------------------------------------------*/
+/* Public variables ---------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/**
+ * START of Section SYSTEM_DRIVER_CONTEXT
+ */
+PLACE_IN_SECTION("SYSTEM_DRIVER_CONTEXT") static tListNode SHciAsynchEventQueue;
+PLACE_IN_SECTION("SYSTEM_DRIVER_CONTEXT") static volatile SHCI_TL_CmdStatus_t SHCICmdStatus;
+PLACE_IN_SECTION("SYSTEM_DRIVER_CONTEXT") static TL_CmdPacket_t *pCmdBuffer;
+PLACE_IN_SECTION("SYSTEM_DRIVER_CONTEXT") SHCI_TL_UserEventFlowStatus_t SHCI_TL_UserEventFlow;
+/**
+ * END of Section SYSTEM_DRIVER_CONTEXT
+ */
+
+static tSHciContext shciContext;
+static void (* StatusNotCallBackFunction)(SHCI_TL_CmdStatus_t status);
+
+static volatile SHCI_TL_CmdRespStatus_t CmdRspStatusFlag;
+
+/* Private function prototypes -----------------------------------------------*/
+static void Cmd_SetStatus(SHCI_TL_CmdStatus_t shcicmdstatus);
+static void TlCmdEvtReceived(TL_EvtPacket_t *shcievt);
+static void TlUserEvtReceived(TL_EvtPacket_t *shcievt);
+static void TlInit(TL_CmdPacket_t *p_cmdbuffer);
+static void OutputCmdTrace(TL_CmdPacket_t *pCmdBuffer);
+static void OutputRspTrace(TL_EvtPacket_t *p_rsp);
+static void OutputEvtTrace(TL_EvtPacket_t *phcievtbuffer);
+
+/* Interface ------- ---------------------------------------------------------*/
+void shci_init(void(* UserEvtRx)(void *pData), void *pConf)
+{
+ StatusNotCallBackFunction = ((SHCI_TL_HciInitConf_t *)pConf)->StatusNotCallBack;
+ shciContext.UserEvtRx = UserEvtRx;
+
+ shci_register_io_bus(&shciContext.io);
+
+ TlInit((TL_CmdPacket_t *)(((SHCI_TL_HciInitConf_t *)pConf)->p_cmdbuffer));
+
+ return;
+}
+
+void shci_user_evt_proc(void)
+{
+ TL_EvtPacket_t *phcievtbuffer;
+ tSHCI_UserEvtRxParam UserEvtRxParam;
+
+ /**
+ * Up to release version v1.2.0, a while loop was implemented to read out events from the queue as long as
+ * it is not empty. However, in a bare metal implementation, this leads to calling in a "blocking" mode
+ * shci_user_evt_proc() as long as events are received without giving the opportunity to run other tasks
+ * in the background.
+ * From now, the events are reported one by one. When it is checked there is still an event pending in the queue,
+ * a request to the user is made to call again shci_user_evt_proc().
+ * This gives the opportunity to the application to run other background tasks between each event.
+ */
+
+ /**
+ * It is more secure to use LST_remove_head()/LST_insert_head() compare to LST_get_next_node()/LST_remove_node()
+ * in case the user overwrite the header where the next/prev pointers are located
+ */
+ if ((LST_is_empty(&SHciAsynchEventQueue) == FALSE) && (SHCI_TL_UserEventFlow != SHCI_TL_UserEventFlow_Disable)) {
+ LST_remove_head(&SHciAsynchEventQueue, (tListNode **)&phcievtbuffer);
+
+ OutputEvtTrace(phcievtbuffer);
+
+ if (shciContext.UserEvtRx != NULL) {
+ UserEvtRxParam.pckt = phcievtbuffer;
+ UserEvtRxParam.status = SHCI_TL_UserEventFlow_Enable;
+ shciContext.UserEvtRx((void *)&UserEvtRxParam);
+ SHCI_TL_UserEventFlow = UserEvtRxParam.status;
+ } else {
+ SHCI_TL_UserEventFlow = SHCI_TL_UserEventFlow_Enable;
+ }
+
+ if (SHCI_TL_UserEventFlow != SHCI_TL_UserEventFlow_Disable) {
+ TL_MM_EvtDone(phcievtbuffer);
+ } else {
+ /**
+ * put back the event in the queue
+ */
+ LST_insert_head(&SHciAsynchEventQueue, (tListNode *)phcievtbuffer);
+ }
+ }
+
+ if ((LST_is_empty(&SHciAsynchEventQueue) == FALSE) && (SHCI_TL_UserEventFlow != SHCI_TL_UserEventFlow_Disable)) {
+ shci_notify_asynch_evt((void *) &SHciAsynchEventQueue);
+ }
+
+ return;
+}
+
+void shci_resume_flow(void)
+{
+ SHCI_TL_UserEventFlow = SHCI_TL_UserEventFlow_Enable;
+
+ /**
+ * It is better to go through the background process as it is not sure from which context this API may
+ * be called
+ */
+ shci_notify_asynch_evt((void *) &SHciAsynchEventQueue);
+
+ return;
+}
+
+void shci_send(uint16_t cmd_code, uint8_t len_cmd_payload, uint8_t *p_cmd_payload, TL_EvtPacket_t *p_rsp)
+{
+ Cmd_SetStatus(SHCI_TL_CmdBusy);
+
+ pCmdBuffer->cmdserial.cmd.cmdcode = cmd_code;
+ pCmdBuffer->cmdserial.cmd.plen = len_cmd_payload;
+
+ memcpy(pCmdBuffer->cmdserial.cmd.payload, p_cmd_payload, len_cmd_payload);
+
+ OutputCmdTrace(pCmdBuffer);
+
+ shciContext.io.Send(0, 0);
+
+ shci_cmd_resp_wait(SHCI_TL_DEFAULT_TIMEOUT);
+
+ /**
+ * The command complete of a system command does not have the header
+ * It starts immediately with the evtserial field
+ */
+ memcpy(&(p_rsp->evtserial), pCmdBuffer, ((TL_EvtSerial_t *)pCmdBuffer)->evt.plen + TL_EVT_HDR_SIZE);
+
+ OutputRspTrace(p_rsp);
+
+ Cmd_SetStatus(SHCI_TL_CmdAvailable);
+
+ return;
+}
+
+void shci_notify_asynch_evt(void *pdata)
+{
+ UNUSED(pdata);
+ /* Need to parse data in future version */
+ shci_user_evt_proc();
+}
+
+void shci_register_io_bus(tSHciIO *fops)
+{
+ /* Register IO bus services */
+ fops->Init = TL_SYS_Init;
+ fops->Send = TL_SYS_SendCmd;
+}
+
+/* Private functions ---------------------------------------------------------*/
+static void TlInit(TL_CmdPacket_t *p_cmdbuffer)
+{
+ TL_SYS_InitConf_t Conf;
+
+ pCmdBuffer = p_cmdbuffer;
+
+ LST_init_head(&SHciAsynchEventQueue);
+
+ Cmd_SetStatus(SHCI_TL_CmdAvailable);
+
+ SHCI_TL_UserEventFlow = SHCI_TL_UserEventFlow_Enable;
+
+ /* Initialize low level driver */
+ if (shciContext.io.Init) {
+
+ Conf.p_cmdbuffer = (uint8_t *)p_cmdbuffer;
+ Conf.IoBusCallBackCmdEvt = TlCmdEvtReceived;
+ Conf.IoBusCallBackUserEvt = TlUserEvtReceived;
+ shciContext.io.Init(&Conf);
+ }
+
+ return;
+}
+
+static void Cmd_SetStatus(SHCI_TL_CmdStatus_t shcicmdstatus)
+{
+ if (shcicmdstatus == SHCI_TL_CmdBusy) {
+ if (StatusNotCallBackFunction != 0) {
+ StatusNotCallBackFunction(SHCI_TL_CmdBusy);
+ }
+ SHCICmdStatus = SHCI_TL_CmdBusy;
+ } else {
+ SHCICmdStatus = SHCI_TL_CmdAvailable;
+ if (StatusNotCallBackFunction != 0) {
+ StatusNotCallBackFunction(SHCI_TL_CmdAvailable);
+ }
+ }
+
+ return;
+}
+
+static void TlCmdEvtReceived(TL_EvtPacket_t *shcievt)
+{
+ (void)(shcievt);
+ shci_cmd_resp_release(0); /**< Notify the application the Cmd response has been received */
+
+ return;
+}
+
+static void TlUserEvtReceived(TL_EvtPacket_t *shcievt)
+{
+ LST_insert_tail(&SHciAsynchEventQueue, (tListNode *)shcievt);
+ shci_notify_asynch_evt((void *) &SHciAsynchEventQueue); /**< Notify the application a full HCI event has been received */
+
+ return;
+}
+
+static void OutputCmdTrace(TL_CmdPacket_t *pCmdBuffer)
+{
+ TL_SHCI_CMD_DBG_MSG("sys cmd: 0x%04X", pCmdBuffer->cmdserial.cmd.cmdcode);
+
+ if (pCmdBuffer->cmdserial.cmd.plen != 0) {
+ TL_SHCI_CMD_DBG_MSG(" payload:");
+ TL_SHCI_CMD_DBG_BUF(pCmdBuffer->cmdserial.cmd.payload, pCmdBuffer->cmdserial.cmd.plen, "");
+ }
+ TL_SHCI_CMD_DBG_MSG("\r\n");
+
+ return;
+}
+
+static void OutputRspTrace(TL_EvtPacket_t *p_rsp)
+{
+ switch (p_rsp->evtserial.evt.evtcode) {
+ case TL_BLEEVT_CC_OPCODE:
+ TL_SHCI_CMD_DBG_MSG("sys rsp: 0x%02X", p_rsp->evtserial.evt.evtcode);
+ TL_SHCI_CMD_DBG_MSG(" cmd opcode: 0x%02X", ((TL_CcEvt_t *)(p_rsp->evtserial.evt.payload))->cmdcode);
+ TL_SHCI_CMD_DBG_MSG(" status: 0x%02X", ((TL_CcEvt_t *)(p_rsp->evtserial.evt.payload))->payload[0]);
+ if ((p_rsp->evtserial.evt.plen - 4) != 0) {
+ TL_SHCI_CMD_DBG_MSG(" payload:");
+ TL_SHCI_CMD_DBG_BUF(&((TL_CcEvt_t *)(p_rsp->evtserial.evt.payload))->payload[1], p_rsp->evtserial.evt.plen - 4, "");
+ }
+ break;
+
+ default:
+ TL_SHCI_CMD_DBG_MSG("unknown sys rsp received: %02X", p_rsp->evtserial.evt.evtcode);
+ break;
+ }
+
+ TL_SHCI_CMD_DBG_MSG("\r\n");
+
+ return;
+}
+
+static void OutputEvtTrace(TL_EvtPacket_t *phcievtbuffer)
+{
+ if (phcievtbuffer->evtserial.evt.evtcode != TL_BLEEVT_VS_OPCODE) {
+ TL_SHCI_EVT_DBG_MSG("unknown sys evt received: %02X", phcievtbuffer->evtserial.evt.evtcode);
+ } else {
+ TL_SHCI_EVT_DBG_MSG("sys evt: 0x%02X", phcievtbuffer->evtserial.evt.evtcode);
+ TL_SHCI_EVT_DBG_MSG(" subevtcode: 0x%04X", ((TL_AsynchEvt_t *)(phcievtbuffer->evtserial.evt.payload))->subevtcode);
+ if ((phcievtbuffer->evtserial.evt.plen - 2) != 0) {
+ TL_SHCI_EVT_DBG_MSG(" payload:");
+ TL_SHCI_EVT_DBG_BUF(((TL_AsynchEvt_t *)(phcievtbuffer->evtserial.evt.payload))->payload, phcievtbuffer->evtserial.evt.plen - 2, "");
+ }
+ }
+
+ TL_SHCI_EVT_DBG_MSG("\r\n");
+
+ return;
+}
+
+/* Weak implementation ----------------------------------------------------------------*/
+__WEAK void shci_cmd_resp_wait(uint32_t timeout)
+{
+ (void)timeout;
+
+ CmdRspStatusFlag = SHCI_TL_CMD_RESP_WAIT;
+ while (CmdRspStatusFlag != SHCI_TL_CMD_RESP_RELEASE);
+
+ return;
+}
+
+__WEAK void shci_cmd_resp_release(uint32_t flag)
+{
+ (void)flag;
+
+ CmdRspStatusFlag = SHCI_TL_CMD_RESP_RELEASE;
+
+ return;
+}
+
+#endif /* STM32WBxx */
+
diff --git a/src/utility/STM32Cube_FW/shci_tl.h b/src/utility/STM32Cube_FW/shci_tl.h
new file mode 100644
index 00000000..f6cc8043
--- /dev/null
+++ b/src/utility/STM32Cube_FW/shci_tl.h
@@ -0,0 +1,169 @@
+/**
+ ******************************************************************************
+ * @file shci_tl.h
+ * @author MCD Application Team
+ * @brief System HCI command header for the system channel
+ ******************************************************************************
+ * @attention
+ *
+ * © Copyright (c) 2019 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+
+#ifndef __SHCI_TL_H_
+#define __SHCI_TL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "tl.h"
+
+/* Exported defines -----------------------------------------------------------*/
+typedef enum {
+ SHCI_TL_UserEventFlow_Disable,
+ SHCI_TL_UserEventFlow_Enable,
+} SHCI_TL_UserEventFlowStatus_t;
+
+typedef enum {
+ SHCI_TL_CmdBusy,
+ SHCI_TL_CmdAvailable
+} SHCI_TL_CmdStatus_t;
+
+/**
+ * @brief Structure used to manage the BUS IO operations.
+ * All the structure fields will point to functions defined at user level.
+ * @{
+ */
+typedef struct {
+ int32_t (* Init)(void *pConf); /**< Pointer to SHCI TL function for the IO Bus initialization */
+ int32_t (* DeInit)(void); /**< Pointer to SHCI TL function for the IO Bus de-initialization */
+ int32_t (* Reset)(void); /**< Pointer to SHCI TL function for the IO Bus reset */
+ int32_t (* Receive)(uint8_t *, uint16_t); /**< Pointer to SHCI TL function for the IO Bus data reception */
+ int32_t (* Send)(uint8_t *, uint16_t); /**< Pointer to SHCI TL function for the IO Bus data transmission */
+ int32_t (* DataAck)(uint8_t *, uint16_t *len); /**< Pointer to SHCI TL function for the IO Bus data ack reception */
+ int32_t (* GetTick)(void); /**< Pointer to BSP function for getting the HAL time base timestamp */
+} tSHciIO;
+/**
+ * @}
+ */
+
+/**
+ * @brief Contain the SHCI context
+ * @{
+ */
+typedef struct {
+ tSHciIO io; /**< Manage the BUS IO operations */
+ void (* UserEvtRx)(void *pData); /**< User System events callback function pointer */
+} tSHciContext;
+
+typedef struct {
+ SHCI_TL_UserEventFlowStatus_t status;
+ TL_EvtPacket_t *pckt;
+} tSHCI_UserEvtRxParam;
+
+typedef struct {
+ uint8_t *p_cmdbuffer;
+ void (* StatusNotCallBack)(SHCI_TL_CmdStatus_t status);
+} SHCI_TL_HciInitConf_t;
+
+/**
+ * shci_send
+ * @brief Send an System HCI Command
+ *
+ * @param : cmd_code = Opcode of the command
+ * @param : len_cmd_payload = Length of the command payload
+ * @param : p_cmd_payload = Address of the command payload
+ * @param : p_rsp_status = Address of the full buffer holding the command complete event
+ * @retval : None
+ */
+void shci_send(uint16_t cmd_code, uint8_t len_cmd_payload, uint8_t *p_cmd_payload, TL_EvtPacket_t *p_rsp_status);
+
+/**
+ * @brief Register IO bus services.
+ * @param fops The SHCI IO structure managing the IO BUS
+ * @retval None
+ */
+void shci_register_io_bus(tSHciIO *fops);
+
+/**
+ * @brief Interrupt service routine that must be called when the system channel
+ * reports a packet has been received
+ *
+ * @param pdata Packet or event pointer
+ * @retval None
+ */
+void shci_notify_asynch_evt(void *pdata);
+
+/**
+ * @brief This function resume the User Event Flow which has been stopped on return
+ * from UserEvtRx() when the User Event has not been processed.
+ *
+ * @param None
+ * @retval None
+ */
+void shci_resume_flow(void);
+
+
+/**
+ * @brief This function is called when an System HCI Command is sent to the CPU2 and the response is waited.
+ * It is called from the same context the System HCI command has been sent.
+ * It shall not return until the command response notified by shci_cmd_resp_release() is received.
+ * A weak implementation is available in shci_tl.c based on polling mechanism
+ * The user may re-implement this function in the application to improve performance :
+ * - It may use UTIL_SEQ_WaitEvt() API when using the Sequencer
+ * - It may use a semaphore when using cmsis_os interface
+ *
+ * @param timeout: Waiting timeout
+ * @retval None
+ */
+void shci_cmd_resp_wait(uint32_t timeout);
+
+/**
+ * @brief This function is called when an System HCI command is received from the CPU2.
+ * A weak implementation is available in shci_tl.c based on polling mechanism
+ * The user may re-implement this function in the application to improve performance :
+ * - It may use UTIL_SEQ_SetEvt() API when using the Sequencer
+ * - It may use a semaphore when using cmsis_os interface
+ *
+ *
+ * @param flag: Release flag
+ * @retval None
+ */
+void shci_cmd_resp_release(uint32_t flag);
+
+
+/**
+ * @brief This process shall be called each time the shci_notify_asynch_evt notification is received
+ *
+ * @param None
+ * @retval None
+ */
+
+void shci_user_evt_proc(void);
+
+/**
+ * @brief Initialize the System Host Controller Interface.
+ * This function must be called before any communication on the System Channel
+ *
+ * @param pData: System events callback function pointer
+ * This callback is triggered when an user event is received on
+ * the System Channel from CPU2.
+ * @param pConf: Configuration structure pointer
+ * @retval None
+ */
+void shci_init(void(* UserEvtRx)(void *pData), void *pConf);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SHCI_TL_H_ */
diff --git a/src/utility/STM32Cube_FW/stm32_wpan_common.h b/src/utility/STM32Cube_FW/stm32_wpan_common.h
new file mode 100644
index 00000000..12f1a583
--- /dev/null
+++ b/src/utility/STM32Cube_FW/stm32_wpan_common.h
@@ -0,0 +1,143 @@
+/**
+ ******************************************************************************
+ * @file stm32_wpan_common.h
+ * @author MCD Application Team
+ * @brief Common file to utilities
+ ******************************************************************************
+ * @attention
+ *
+ * © Copyright (c) 2018 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software component is licensed by ST under Ultimate Liberty license
+ * SLA0044, the "License"; You may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at:
+ * www.st.com/SLA0044
+ *
+ ******************************************************************************
+ */
+
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32_WPAN_COMMON_H
+#define __STM32_WPAN_COMMON_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __ASM __asm /*!< asm keyword for GNU Compiler */
+#define __INLINE inline /*!< inline keyword for GNU Compiler */
+#define __STATIC_INLINE static inline
+
+#include
+#include
+#include
+#include
+#include
+#include "cmsis_compiler.h"
+
+/* -------------------------------- *
+ * Basic definitions *
+ * -------------------------------- */
+
+#undef NULL
+#define NULL 0U
+
+#undef FALSE
+#define FALSE 0U
+
+#undef TRUE
+#define TRUE (!0U)
+
+/* -------------------------------- *
+ * Critical Section definition *
+ * -------------------------------- */
+#undef BACKUP_PRIMASK
+#define BACKUP_PRIMASK() uint32_t primask_bit= __get_PRIMASK()
+
+#undef DISABLE_IRQ
+#define DISABLE_IRQ() __disable_irq()
+
+#undef RESTORE_PRIMASK
+#define RESTORE_PRIMASK() __set_PRIMASK(primask_bit)
+
+/* -------------------------------- *
+ * Macro delimiters *
+ * -------------------------------- */
+#undef M_BEGIN
+#define M_BEGIN do {
+
+#undef M_END
+#define M_END } while(0)
+
+/* -------------------------------- *
+ * Some useful macro definitions *
+ * -------------------------------- */
+#undef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+
+#undef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+#undef MODINC
+#define MODINC( a, m ) M_BEGIN (a)++; if ((a)>=(m)) (a)=0; M_END
+
+#undef MODDEC
+#define MODDEC( a, m ) M_BEGIN if ((a)==0) (a)=(m); (a)--; M_END
+
+#undef MODADD
+#define MODADD( a, b, m ) M_BEGIN (a)+=(b); if ((a)>=(m)) (a)-=(m); M_END
+
+#undef MODSUB
+#define MODSUB( a, b, m ) MODADD( a, (m)-(b), m )
+
+#undef ALIGN
+#ifdef WIN32
+#define ALIGN(n)
+#else
+#define ALIGN(n) __attribute__((aligned(n)))
+#endif
+
+#undef PAUSE
+#define PAUSE( t ) M_BEGIN \
+ volatile int _i; \
+ for ( _i = t; _i > 0; _i -- ); \
+ M_END
+#undef DIVF
+#define DIVF( x, y ) ((x)/(y))
+
+#undef DIVC
+#define DIVC( x, y ) (((x)+(y)-1)/(y))
+
+#undef DIVR
+#define DIVR( x, y ) (((x)+((y)/2))/(y))
+
+#undef SHRR
+#define SHRR( x, n ) ((((x)>>((n)-1))+1)>>1)
+
+#undef BITN
+#define BITN( w, n ) (((w)[(n)/32] >> ((n)%32)) & 1)
+
+#undef BITNSET
+#define BITNSET( w, n, b ) M_BEGIN (w)[(n)/32] |= ((U32)(b))<<((n)%32); M_END
+
+/* -------------------------------- *
+ * Section attribute *
+ * -------------------------------- */
+#undef PLACE_IN_SECTION
+#define PLACE_IN_SECTION( __x__ ) __attribute__((section (__x__)))
+
+/* ----------------------------------- *
+ * Packed usage (compiler dependent) *
+ * ----------------------------------- */
+#undef PACKED_STRUCT
+#define PACKED_STRUCT struct __packed
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__STM32_WPAN_COMMON_H */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/src/utility/STM32Cube_FW/stm_list.c b/src/utility/STM32Cube_FW/stm_list.c
new file mode 100644
index 00000000..509b2b57
--- /dev/null
+++ b/src/utility/STM32Cube_FW/stm_list.c
@@ -0,0 +1,206 @@
+/**
+ ******************************************************************************
+ * @file stm_list.c
+ * @author MCD Application Team
+ * @brief TCircular Linked List Implementation.
+ ******************************************************************************
+ * @attention
+ *
+ * © Copyright (c) 2019 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+#if defined(STM32WBxx)
+/******************************************************************************
+ * Include Files
+ ******************************************************************************/
+#include "stm_list.h"
+#include "cmsis_gcc.h"
+#include "stm32_wpan_common.h"
+
+/******************************************************************************
+ * Function Definitions
+ ******************************************************************************/
+void LST_init_head(tListNode *listHead)
+{
+ listHead->next = listHead;
+ listHead->prev = listHead;
+}
+
+bool LST_is_empty(tListNode *listHead)
+{
+ uint32_t primask_bit;
+ bool return_value;
+
+ primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
+ __disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
+ if (listHead->next == listHead) {
+ return_value = TRUE;
+ } else {
+ return_value = FALSE;
+ }
+ __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
+
+ return return_value;
+}
+
+void LST_insert_head(tListNode *listHead, tListNode *node)
+{
+ uint32_t primask_bit;
+
+ primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
+ __disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
+
+ node->next = listHead->next;
+ node->prev = listHead;
+ listHead->next = node;
+ (node->next)->prev = node;
+
+ __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
+}
+
+
+void LST_insert_tail(tListNode *listHead, tListNode *node)
+{
+ uint32_t primask_bit;
+
+ primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
+ __disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
+
+ node->next = listHead;
+ node->prev = listHead->prev;
+ listHead->prev = node;
+ (node->prev)->next = node;
+
+ __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
+}
+
+
+void LST_remove_node(tListNode *node)
+{
+ uint32_t primask_bit;
+
+ primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
+ __disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
+
+ (node->prev)->next = node->next;
+ (node->next)->prev = node->prev;
+
+ __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
+}
+
+
+void LST_remove_head(tListNode *listHead, tListNode **node)
+{
+ uint32_t primask_bit;
+
+ primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
+ __disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
+
+ *node = listHead->next;
+ LST_remove_node(listHead->next);
+
+ __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
+}
+
+
+void LST_remove_tail(tListNode *listHead, tListNode **node)
+{
+ uint32_t primask_bit;
+
+ primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
+ __disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
+
+ *node = listHead->prev;
+ LST_remove_node(listHead->prev);
+
+ __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
+}
+
+
+void LST_insert_node_after(tListNode *node, tListNode *ref_node)
+{
+ uint32_t primask_bit;
+
+ primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
+ __disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
+
+ node->next = ref_node->next;
+ node->prev = ref_node;
+ ref_node->next = node;
+ (node->next)->prev = node;
+
+ __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
+}
+
+
+void LST_insert_node_before(tListNode *node, tListNode *ref_node)
+{
+ uint32_t primask_bit;
+
+ primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
+ __disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
+
+ node->next = ref_node;
+ node->prev = ref_node->prev;
+ ref_node->prev = node;
+ (node->prev)->next = node;
+
+ __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
+}
+
+
+int LST_get_size(tListNode *listHead)
+{
+ int size = 0;
+ tListNode *temp;
+ uint32_t primask_bit;
+
+ primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
+ __disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
+
+ temp = listHead->next;
+ while (temp != listHead) {
+ size++;
+ temp = temp->next;
+ }
+
+ __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
+
+ return (size);
+}
+
+void LST_get_next_node(tListNode *ref_node, tListNode **node)
+{
+ uint32_t primask_bit;
+
+ primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
+ __disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
+
+ *node = ref_node->next;
+
+ __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
+}
+
+
+void LST_get_prev_node(tListNode *ref_node, tListNode **node)
+{
+ uint32_t primask_bit;
+
+ primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
+ __disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
+
+ *node = ref_node->prev;
+
+ __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
+}
+
+#endif /* STM32WBxx */
+
diff --git a/src/utility/STM32Cube_FW/stm_list.h b/src/utility/STM32Cube_FW/stm_list.h
new file mode 100644
index 00000000..885b50c1
--- /dev/null
+++ b/src/utility/STM32Cube_FW/stm_list.h
@@ -0,0 +1,66 @@
+/**
+ ******************************************************************************
+ * @file stm_list.h
+ * @author MCD Application Team
+ * @brief Header file for linked list library.
+ ******************************************************************************
+ * @attention
+ *
+ * © Copyright (c) 2019 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+
+#ifndef _STM_LIST_H_
+#define _STM_LIST_H_
+
+/* Includes ------------------------------------------------------------------*/
+
+#include "stdbool.h"
+#include "stm32_wpan_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef PACKED_STRUCT _tListNode {
+ struct _tListNode *next;
+ struct _tListNode *prev;
+} tListNode;
+
+void LST_init_head(tListNode *listHead);
+
+bool LST_is_empty(tListNode *listHead);
+
+void LST_insert_head(tListNode *listHead, tListNode *node);
+
+void LST_insert_tail(tListNode *listHead, tListNode *node);
+
+void LST_remove_node(tListNode *node);
+
+void LST_remove_head(tListNode *listHead, tListNode **node);
+
+void LST_remove_tail(tListNode *listHead, tListNode **node);
+
+void LST_insert_node_after(tListNode *node, tListNode *ref_node);
+
+void LST_insert_node_before(tListNode *node, tListNode *ref_node);
+
+int LST_get_size(tListNode *listHead);
+
+void LST_get_next_node(tListNode *ref_node, tListNode **node);
+
+void LST_get_prev_node(tListNode *ref_node, tListNode **node);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _STM_LIST_H_ */
diff --git a/src/utility/STM32Cube_FW/tl.h b/src/utility/STM32Cube_FW/tl.h
new file mode 100644
index 00000000..f8abf288
--- /dev/null
+++ b/src/utility/STM32Cube_FW/tl.h
@@ -0,0 +1,294 @@
+/**
+ ******************************************************************************
+ * @file tl.h
+ * @author MCD Application Team
+ * @brief Header for tl module
+ ******************************************************************************
+ * @attention
+ *
+ * © Copyright (c) 2019 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __TL_H
+#define __TL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32_wpan_common.h"
+
+/* Exported defines -----------------------------------------------------------*/
+#define TL_BLECMD_PKT_TYPE ( 0x01 )
+#define TL_ACL_DATA_PKT_TYPE ( 0x02 )
+#define TL_BLEEVT_PKT_TYPE ( 0x04 )
+#define TL_OTCMD_PKT_TYPE ( 0x08 )
+#define TL_OTRSP_PKT_TYPE ( 0x09 )
+#define TL_CLICMD_PKT_TYPE ( 0x0A )
+#define TL_OTNOT_PKT_TYPE ( 0x0C )
+#define TL_OTACK_PKT_TYPE ( 0x0D )
+#define TL_CLINOT_PKT_TYPE ( 0x0E )
+#define TL_CLIACK_PKT_TYPE ( 0x0F )
+#define TL_SYSCMD_PKT_TYPE ( 0x10 )
+#define TL_SYSRSP_PKT_TYPE ( 0x11 )
+#define TL_SYSEVT_PKT_TYPE ( 0x12 )
+#define TL_CLIRESP_PKT_TYPE ( 0x15 )
+#define TL_M0CMD_PKT_TYPE ( 0x16 )
+#define TL_LOCCMD_PKT_TYPE ( 0x20 )
+#define TL_LOCRSP_PKT_TYPE ( 0x21 )
+#define TL_TRACES_APP_PKT_TYPE ( 0x40 )
+#define TL_TRACES_WL_PKT_TYPE ( 0x41 )
+
+#define TL_CMD_HDR_SIZE (4)
+#define TL_EVT_HDR_SIZE (3)
+#define TL_EVT_CS_PAYLOAD_SIZE (4)
+
+#define TL_BLEEVT_CC_OPCODE (0x0E)
+#define TL_BLEEVT_CS_OPCODE (0x0F)
+#define TL_BLEEVT_VS_OPCODE (0xFF)
+
+#define TL_BLEEVT_CS_PACKET_SIZE (TL_EVT_HDR_SIZE + sizeof(TL_CsEvt_t))
+#define TL_BLEEVT_CS_BUFFER_SIZE (sizeof(TL_PacketHeader_t) + TL_BLEEVT_CS_PACKET_SIZE)
+
+/* Exported types ------------------------------------------------------------*/
+/**< Packet header */
+typedef PACKED_STRUCT {
+ uint32_t *next;
+ uint32_t *prev;
+} TL_PacketHeader_t;
+
+/*******************************************************************************
+ * Event type
+ */
+
+/**
+ * This the payload of TL_Evt_t for a command status event
+ */
+typedef PACKED_STRUCT {
+ uint8_t status;
+ uint8_t numcmd;
+ uint16_t cmdcode;
+} TL_CsEvt_t;
+
+/**
+ * This the payload of TL_Evt_t for a command complete event
+ */
+typedef PACKED_STRUCT {
+ uint8_t numcmd;
+ uint16_t cmdcode;
+ uint8_t payload[1];
+} TL_CcEvt_t;
+
+/**
+ * This the payload of TL_Evt_t for an asynchronous event
+ */
+typedef PACKED_STRUCT {
+ uint16_t subevtcode;
+ uint8_t payload[1];
+} TL_AsynchEvt_t;
+
+typedef PACKED_STRUCT {
+ uint8_t evtcode;
+ uint8_t plen;
+ uint8_t payload[1];
+} TL_Evt_t;
+
+typedef PACKED_STRUCT {
+ uint8_t type;
+ TL_Evt_t evt;
+} TL_EvtSerial_t;
+
+/**
+ * This format shall be used for all events (asynchronous and command response) reported
+ * by the CPU2 except for the command response of a system command where the header is not there
+ * and the format to be used shall be TL_EvtSerial_t.
+ * Note: Be careful that the asynchronous events reported by the CPU2 on the system channel do
+ * include the header and shall use TL_EvtPacket_t format. Only the command response format on the
+ * system channel is different.
+ */
+typedef PACKED_STRUCT {
+ TL_PacketHeader_t header;
+ TL_EvtSerial_t evtserial;
+} TL_EvtPacket_t;
+
+/*****************************************************************************************
+ * Command type
+ */
+
+typedef PACKED_STRUCT {
+ uint16_t cmdcode;
+ uint8_t plen;
+ uint8_t payload[255];
+} TL_Cmd_t;
+
+typedef PACKED_STRUCT {
+ uint8_t type;
+ TL_Cmd_t cmd;
+} TL_CmdSerial_t;
+
+typedef PACKED_STRUCT {
+ TL_PacketHeader_t header;
+ TL_CmdSerial_t cmdserial;
+} TL_CmdPacket_t;
+
+/*****************************************************************************************
+ * HCI ACL DATA type
+ */
+typedef PACKED_STRUCT {
+ uint8_t type;
+ uint16_t handle;
+ uint16_t length;
+ uint8_t acl_data[1];
+} TL_AclDataSerial_t;
+
+typedef PACKED_STRUCT {
+ TL_PacketHeader_t header;
+ TL_AclDataSerial_t AclDataSerial;
+} TL_AclDataPacket_t;
+
+typedef struct {
+ uint8_t *p_BleSpareEvtBuffer;
+ uint8_t *p_SystemSpareEvtBuffer;
+ uint8_t *p_AsynchEvtPool;
+ uint32_t AsynchEvtPoolSize;
+ uint8_t *p_TracesEvtPool;
+ uint32_t TracesEvtPoolSize;
+} TL_MM_Config_t;
+
+typedef struct {
+ uint8_t *p_ThreadOtCmdRspBuffer;
+ uint8_t *p_ThreadCliRspBuffer;
+ uint8_t *p_ThreadNotAckBuffer;
+} TL_TH_Config_t;
+
+typedef struct {
+ uint8_t *p_LldTestsCliCmdRspBuffer;
+ uint8_t *p_LldTestsM0CmdBuffer;
+} TL_LLD_tests_Config_t;
+
+typedef struct {
+ uint8_t *p_LldBleCmdRspBuffer;
+ uint8_t *p_LldBleM0CmdBuffer;
+} TL_LLD_BLE_Config_t;
+
+typedef struct {
+ uint8_t *p_Mac_802_15_4_CmdRspBuffer;
+ uint8_t *p_Mac_802_15_4_NotAckBuffer;
+} TL_MAC_802_15_4_Config_t;
+
+typedef struct {
+ uint8_t *p_ZigbeeOtCmdRspBuffer;
+ uint8_t *p_ZigbeeNotAckBuffer;
+ uint8_t *p_ZigbeeNotifRequestBuffer;
+} TL_ZIGBEE_Config_t;
+
+/**
+ * @brief Contain the BLE HCI Init Configuration
+ * @{
+ */
+typedef struct {
+ void (* IoBusEvtCallBack)(TL_EvtPacket_t *phcievt);
+ void (* IoBusAclDataTxAck)(void);
+ uint8_t *p_cmdbuffer;
+ uint8_t *p_AclDataBuffer;
+} TL_BLE_InitConf_t;
+
+/**
+ * @brief Contain the SYSTEM HCI Init Configuration
+ * @{
+ */
+typedef struct {
+ void (* IoBusCallBackCmdEvt)(TL_EvtPacket_t *phcievt);
+ void (* IoBusCallBackUserEvt)(TL_EvtPacket_t *phcievt);
+ uint8_t *p_cmdbuffer;
+} TL_SYS_InitConf_t;
+
+/* Exported constants --------------------------------------------------------*/
+/* External variables --------------------------------------------------------*/
+/* Exported macros -----------------------------------------------------------*/
+/* Exported functions ------------------------------------------------------- */
+
+/******************************************************************************
+ * GENERAL
+ ******************************************************************************/
+void TL_Enable(void);
+void TL_Init(void);
+
+/******************************************************************************
+ * BLE
+ ******************************************************************************/
+int32_t TL_BLE_Init(void *pConf);
+int32_t TL_BLE_SendCmd(uint8_t *buffer, uint16_t size);
+int32_t TL_BLE_SendAclData(uint8_t *buffer, uint16_t size);
+
+/******************************************************************************
+ * SYSTEM
+ ******************************************************************************/
+int32_t TL_SYS_Init(void *pConf);
+int32_t TL_SYS_SendCmd(uint8_t *buffer, uint16_t size);
+
+/******************************************************************************
+ * THREAD
+ ******************************************************************************/
+void TL_THREAD_Init(TL_TH_Config_t *p_Config);
+void TL_OT_SendCmd(void);
+void TL_CLI_SendCmd(void);
+void TL_OT_CmdEvtReceived(TL_EvtPacket_t *Otbuffer);
+void TL_THREAD_NotReceived(TL_EvtPacket_t *Notbuffer);
+void TL_THREAD_SendAck(void);
+void TL_THREAD_CliSendAck(void);
+void TL_THREAD_CliNotReceived(TL_EvtPacket_t *Notbuffer);
+
+/******************************************************************************
+ * LLD TESTS
+ ******************************************************************************/
+void TL_LLDTESTS_Init(TL_LLD_tests_Config_t *p_Config);
+void TL_LLDTESTS_SendCliCmd(void);
+void TL_LLDTESTS_ReceiveCliRsp(TL_CmdPacket_t *Notbuffer);
+void TL_LLDTESTS_SendCliRspAck(void);
+void TL_LLDTESTS_ReceiveM0Cmd(TL_CmdPacket_t *Notbuffer);
+void TL_LLDTESTS_SendM0CmdAck(void);
+
+/******************************************************************************
+ * LLD BLE
+ ******************************************************************************/
+void TL_LLD_BLE_Init(TL_LLD_BLE_Config_t *p_Config);
+void TL_LLD_BLE_SendCliCmd(void);
+void TL_LLD_BLE_ReceiveCliRsp(TL_CmdPacket_t *Notbuffer);
+void TL_LLD_BLE_SendCliRspAck(void);
+void TL_LLD_BLE_ReceiveM0Cmd(TL_CmdPacket_t *Notbuffer);
+void TL_LLD_BLE_SendM0CmdAck(void);
+void TL_LLD_BLE_SendCmd(void);
+void TL_LLD_BLE_ReceiveRsp(TL_CmdPacket_t *Notbuffer);
+void TL_LLD_BLE_SendRspAck(void);
+/******************************************************************************
+ * MEMORY MANAGER
+ ******************************************************************************/
+void TL_MM_Init(TL_MM_Config_t *p_Config);
+void TL_MM_EvtDone(TL_EvtPacket_t *hcievt);
+
+/******************************************************************************
+ * TRACES
+ ******************************************************************************/
+void TL_TRACES_Init(void);
+void TL_TRACES_EvtReceived(TL_EvtPacket_t *hcievt);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /*__TL_H */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/src/utility/STM32Cube_FW/tl_mbox.c b/src/utility/STM32Cube_FW/tl_mbox.c
new file mode 100644
index 00000000..a235493d
--- /dev/null
+++ b/src/utility/STM32Cube_FW/tl_mbox.c
@@ -0,0 +1,545 @@
+/**
+ ******************************************************************************
+ * @file tl_mbox.c
+ * @author MCD Application Team
+ * @brief Transport layer for the mailbox interface
+ ******************************************************************************
+ * @attention
+ *
+ * © Copyright (c) 2019 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software component is licensed by ST under BSD 3-Clause license,
+ * the "License"; You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ *
+ ******************************************************************************
+ */
+
+#if defined(STM32WBxx)
+/* Includes ------------------------------------------------------------------*/
+#include "stm32_wpan_common.h"
+#include "hw.h"
+
+#include "stm_list.h"
+#include "tl.h"
+#include "mbox_def.h"
+
+/**
+ * These traces are not yet supported in an usual way in the delivery package
+ * They can enabled by adding the definition of TL_MM_DBG_EN in the preprocessor option in the IDE
+ */
+#if(TL_MM_DBG_EN != 0)
+ #include "app_conf.h"
+ #include "dbg_trace.h"
+#endif
+
+#if (TL_MM_DBG_EN != 0)
+ #define TL_MM_DBG__MSG PRINT_MESG_DBG
+#else
+ #define TL_MM_DBG__MSG(...)
+#endif
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+
+/**< reference table */
+PLACE_IN_SECTION("MAPPING_TABLE") static volatile MB_RefTable_t TL_RefTable;
+PLACE_IN_SECTION("MB_MEM1") ALIGN(4) static MB_DeviceInfoTable_t TL_DeviceInfoTable;
+PLACE_IN_SECTION("MB_MEM1") ALIGN(4) static MB_BleTable_t TL_BleTable;
+PLACE_IN_SECTION("MB_MEM1") ALIGN(4) static MB_ThreadTable_t TL_ThreadTable;
+PLACE_IN_SECTION("MB_MEM1") ALIGN(4) static MB_LldTestsTable_t TL_LldTestsTable;
+PLACE_IN_SECTION("MB_MEM1") ALIGN(4) static MB_LldBleTable_t TL_LldBleTable;
+PLACE_IN_SECTION("MB_MEM1") ALIGN(4) static MB_SysTable_t TL_SysTable;
+PLACE_IN_SECTION("MB_MEM1") ALIGN(4) static MB_MemManagerTable_t TL_MemManagerTable;
+PLACE_IN_SECTION("MB_MEM1") ALIGN(4) static MB_TracesTable_t TL_TracesTable;
+
+/**< tables */
+PLACE_IN_SECTION("MB_MEM1") ALIGN(4) static tListNode FreeBufQueue;
+PLACE_IN_SECTION("MB_MEM1") ALIGN(4) static tListNode TracesEvtQueue;
+PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t CsBuffer[sizeof(TL_PacketHeader_t) + TL_EVT_HDR_SIZE + sizeof(TL_CsEvt_t)];
+PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static tListNode EvtQueue;
+PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static tListNode SystemEvtQueue;
+
+
+static tListNode LocalFreeBufQueue;
+static void (* BLE_IoBusEvtCallBackFunction)(TL_EvtPacket_t *phcievt);
+static void (* BLE_IoBusAclDataTxAck)(void);
+static void (* SYS_CMD_IoBusCallBackFunction)(TL_EvtPacket_t *phcievt);
+static void (* SYS_EVT_IoBusCallBackFunction)(TL_EvtPacket_t *phcievt);
+
+
+/* Global variables ----------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+static void SendFreeBuf(void);
+static void OutputMemReleaseTrace(TL_EvtPacket_t *phcievt);
+
+/* Public Functions Definition ------------------------------------------------------*/
+
+/******************************************************************************
+ * GENERAL
+ ******************************************************************************/
+void TL_Enable(void)
+{
+ HW_IPCC_Enable();
+
+ return;
+}
+
+
+void TL_Init(void)
+{
+ TL_RefTable.p_device_info_table = &TL_DeviceInfoTable;
+ TL_RefTable.p_ble_table = &TL_BleTable;
+ TL_RefTable.p_thread_table = &TL_ThreadTable;
+ TL_RefTable.p_lld_tests_table = &TL_LldTestsTable;
+ TL_RefTable.p_lld_ble_table = &TL_LldBleTable;
+ TL_RefTable.p_sys_table = &TL_SysTable;
+ TL_RefTable.p_mem_manager_table = &TL_MemManagerTable;
+ TL_RefTable.p_traces_table = &TL_TracesTable;
+
+ HW_IPCC_Init();
+
+ return;
+}
+
+/******************************************************************************
+ * BLE
+ ******************************************************************************/
+int32_t TL_BLE_Init(void *pConf)
+{
+ MB_BleTable_t *p_bletable;
+
+ TL_BLE_InitConf_t *pInitHciConf = (TL_BLE_InitConf_t *) pConf;
+
+ LST_init_head(&EvtQueue);
+
+ p_bletable = TL_RefTable.p_ble_table;
+
+ p_bletable->pcmd_buffer = pInitHciConf->p_cmdbuffer;
+ p_bletable->phci_acl_data_buffer = pInitHciConf->p_AclDataBuffer;
+ p_bletable->pcs_buffer = (uint8_t *)CsBuffer;
+ p_bletable->pevt_queue = (uint8_t *)&EvtQueue;
+
+ HW_IPCC_BLE_Init();
+
+ BLE_IoBusEvtCallBackFunction = pInitHciConf->IoBusEvtCallBack;
+ BLE_IoBusAclDataTxAck = pInitHciConf->IoBusAclDataTxAck;
+
+ return 0;
+}
+
+int32_t TL_BLE_SendCmd(uint8_t *buffer, uint16_t size)
+{
+ (void)(buffer);
+ (void)(size);
+
+ ((TL_CmdPacket_t *)(TL_RefTable.p_ble_table->pcmd_buffer))->cmdserial.type = TL_BLECMD_PKT_TYPE;
+
+ HW_IPCC_BLE_SendCmd();
+
+ return 0;
+}
+
+void HW_IPCC_BLE_RxEvtNot(void)
+{
+ TL_EvtPacket_t *phcievt;
+
+ while (LST_is_empty(&EvtQueue) == FALSE) {
+ LST_remove_head(&EvtQueue, (tListNode **)&phcievt);
+
+ BLE_IoBusEvtCallBackFunction(phcievt);
+ }
+
+ return;
+}
+
+int32_t TL_BLE_SendAclData(uint8_t *buffer, uint16_t size)
+{
+ (void)(buffer);
+ (void)(size);
+
+ ((TL_AclDataPacket_t *)(TL_RefTable.p_ble_table->phci_acl_data_buffer))->AclDataSerial.type = TL_ACL_DATA_PKT_TYPE;
+
+ HW_IPCC_BLE_SendAclData();
+
+ return 0;
+}
+
+void HW_IPCC_BLE_AclDataAckNot(void)
+{
+ BLE_IoBusAclDataTxAck();
+
+ return;
+}
+
+/******************************************************************************
+ * SYSTEM
+ ******************************************************************************/
+int32_t TL_SYS_Init(void *pConf)
+{
+ MB_SysTable_t *p_systable;
+
+ TL_SYS_InitConf_t *pInitHciConf = (TL_SYS_InitConf_t *) pConf;
+
+ LST_init_head(&SystemEvtQueue);
+ p_systable = TL_RefTable.p_sys_table;
+ p_systable->pcmd_buffer = pInitHciConf->p_cmdbuffer;
+ p_systable->sys_queue = (uint8_t *)&SystemEvtQueue;
+
+ HW_IPCC_SYS_Init();
+
+ SYS_CMD_IoBusCallBackFunction = pInitHciConf->IoBusCallBackCmdEvt;
+ SYS_EVT_IoBusCallBackFunction = pInitHciConf->IoBusCallBackUserEvt;
+
+ return 0;
+}
+
+int32_t TL_SYS_SendCmd(uint8_t *buffer, uint16_t size)
+{
+ (void)(buffer);
+ (void)(size);
+
+ ((TL_CmdPacket_t *)(TL_RefTable.p_sys_table->pcmd_buffer))->cmdserial.type = TL_SYSCMD_PKT_TYPE;
+
+ HW_IPCC_SYS_SendCmd();
+
+ return 0;
+}
+
+void HW_IPCC_SYS_CmdEvtNot(void)
+{
+ SYS_CMD_IoBusCallBackFunction((TL_EvtPacket_t *)(TL_RefTable.p_sys_table->pcmd_buffer));
+
+ return;
+}
+
+void HW_IPCC_SYS_EvtNot(void)
+{
+ TL_EvtPacket_t *p_evt;
+
+ while (LST_is_empty(&SystemEvtQueue) == FALSE) {
+ LST_remove_head(&SystemEvtQueue, (tListNode **)&p_evt);
+ SYS_EVT_IoBusCallBackFunction(p_evt);
+ }
+
+ return;
+}
+
+/******************************************************************************
+ * THREAD
+ ******************************************************************************/
+#ifdef THREAD_WB
+void TL_THREAD_Init(TL_TH_Config_t *p_Config)
+{
+ MB_ThreadTable_t *p_thread_table;
+
+ p_thread_table = TL_RefTable.p_thread_table;
+
+ p_thread_table->clicmdrsp_buffer = p_Config->p_ThreadCliRspBuffer;
+ p_thread_table->otcmdrsp_buffer = p_Config->p_ThreadOtCmdRspBuffer;
+ p_thread_table->notack_buffer = p_Config->p_ThreadNotAckBuffer;
+
+ HW_IPCC_THREAD_Init();
+
+ return;
+}
+
+void TL_OT_SendCmd(void)
+{
+ ((TL_CmdPacket_t *)(TL_RefTable.p_thread_table->otcmdrsp_buffer))->cmdserial.type = TL_OTCMD_PKT_TYPE;
+
+ HW_IPCC_OT_SendCmd();
+
+ return;
+}
+
+void TL_CLI_SendCmd(void)
+{
+ ((TL_CmdPacket_t *)(TL_RefTable.p_thread_table->clicmdrsp_buffer))->cmdserial.type = TL_CLICMD_PKT_TYPE;
+
+ HW_IPCC_CLI_SendCmd();
+
+ return;
+}
+
+void TL_THREAD_SendAck(void)
+{
+ ((TL_CmdPacket_t *)(TL_RefTable.p_thread_table->notack_buffer))->cmdserial.type = TL_OTACK_PKT_TYPE;
+
+ HW_IPCC_THREAD_SendAck();
+
+ return;
+}
+
+void TL_THREAD_CliSendAck(void)
+{
+ ((TL_CmdPacket_t *)(TL_RefTable.p_thread_table->notack_buffer))->cmdserial.type = TL_OTACK_PKT_TYPE;
+
+ HW_IPCC_THREAD_CliSendAck();
+
+ return;
+}
+
+void HW_IPCC_OT_CmdEvtNot(void)
+{
+ TL_OT_CmdEvtReceived((TL_EvtPacket_t *)(TL_RefTable.p_thread_table->otcmdrsp_buffer));
+
+ return;
+}
+
+void HW_IPCC_THREAD_EvtNot(void)
+{
+ TL_THREAD_NotReceived((TL_EvtPacket_t *)(TL_RefTable.p_thread_table->notack_buffer));
+
+ return;
+}
+
+void HW_IPCC_THREAD_CliEvtNot(void)
+{
+ TL_THREAD_CliNotReceived((TL_EvtPacket_t *)(TL_RefTable.p_thread_table->clicmdrsp_buffer));
+
+ return;
+}
+
+__WEAK void TL_OT_CmdEvtReceived(TL_EvtPacket_t *Otbuffer) {};
+__WEAK void TL_THREAD_NotReceived(TL_EvtPacket_t *Notbuffer) {};
+__WEAK void TL_THREAD_CliNotReceived(TL_EvtPacket_t *Notbuffer) {};
+
+#endif /* THREAD_WB */
+
+/******************************************************************************
+ * LLD TESTS
+ ******************************************************************************/
+#ifdef LLD_TESTS_WB
+void TL_LLDTESTS_Init(TL_LLD_tests_Config_t *p_Config)
+{
+ MB_LldTestsTable_t *p_lld_tests_table;
+
+ p_lld_tests_table = TL_RefTable.p_lld_tests_table;
+ p_lld_tests_table->clicmdrsp_buffer = p_Config->p_LldTestsCliCmdRspBuffer;
+ p_lld_tests_table->m0cmd_buffer = p_Config->p_LldTestsM0CmdBuffer;
+ HW_IPCC_LLDTESTS_Init();
+ return;
+}
+
+void TL_LLDTESTS_SendCliCmd(void)
+{
+ ((TL_CmdPacket_t *)(TL_RefTable.p_lld_tests_table->clicmdrsp_buffer))->cmdserial.type = TL_CLICMD_PKT_TYPE;
+ HW_IPCC_LLDTESTS_SendCliCmd();
+ return;
+}
+
+void HW_IPCC_LLDTESTS_ReceiveCliRsp(void)
+{
+ TL_LLDTESTS_ReceiveCliRsp((TL_CmdPacket_t *)(TL_RefTable.p_lld_tests_table->clicmdrsp_buffer));
+ return;
+}
+
+void TL_LLDTESTS_SendCliRspAck(void)
+{
+ HW_IPCC_LLDTESTS_SendCliRspAck();
+ return;
+}
+
+void HW_IPCC_LLDTESTS_ReceiveM0Cmd(void)
+{
+ TL_LLDTESTS_ReceiveM0Cmd((TL_CmdPacket_t *)(TL_RefTable.p_lld_tests_table->m0cmd_buffer));
+ return;
+}
+
+
+void TL_LLDTESTS_SendM0CmdAck(void)
+{
+ HW_IPCC_LLDTESTS_SendM0CmdAck();
+ return;
+}
+
+__WEAK void TL_LLDTESTS_ReceiveCliRsp(TL_CmdPacket_t *Notbuffer) {};
+__WEAK void TL_LLDTESTS_ReceiveM0Cmd(TL_CmdPacket_t *Notbuffer) {};
+#endif /* LLD_TESTS_WB */
+
+/******************************************************************************
+ * LLD BLE
+ ******************************************************************************/
+#ifdef LLD_BLE_WB
+void TL_LLD_BLE_Init(TL_LLD_BLE_Config_t *p_Config)
+{
+ MB_LldBleTable_t *p_lld_ble_table;
+
+ p_lld_ble_table = TL_RefTable.p_lld_ble_table;
+ p_lld_ble_table->cmdrsp_buffer = p_Config->p_LldBleCmdRspBuffer;
+ p_lld_ble_table->m0cmd_buffer = p_Config->p_LldBleM0CmdBuffer;
+ HW_IPCC_LLD_BLE_Init();
+ return;
+}
+
+void TL_LLD_BLE_SendCliCmd(void)
+{
+ ((TL_CmdPacket_t *)(TL_RefTable.p_lld_ble_table->cmdrsp_buffer))->cmdserial.type = TL_CLICMD_PKT_TYPE;
+ HW_IPCC_LLD_BLE_SendCliCmd();
+ return;
+}
+
+void HW_IPCC_LLD_BLE_ReceiveCliRsp(void)
+{
+ TL_LLD_BLE_ReceiveCliRsp((TL_CmdPacket_t *)(TL_RefTable.p_lld_ble_table->cmdrsp_buffer));
+ return;
+}
+
+void TL_LLD_BLE_SendCliRspAck(void)
+{
+ HW_IPCC_LLD_BLE_SendCliRspAck();
+ return;
+}
+
+void HW_IPCC_LLD_BLE_ReceiveM0Cmd(void)
+{
+ TL_LLD_BLE_ReceiveM0Cmd((TL_CmdPacket_t *)(TL_RefTable.p_lld_ble_table->m0cmd_buffer));
+ return;
+}
+
+
+void TL_LLD_BLE_SendM0CmdAck(void)
+{
+ HW_IPCC_LLD_BLE_SendM0CmdAck();
+ return;
+}
+
+__WEAK void TL_LLD_BLE_ReceiveCliRsp(TL_CmdPacket_t *Notbuffer) {};
+__WEAK void TL_LLD_BLE_ReceiveM0Cmd(TL_CmdPacket_t *Notbuffer) {};
+
+/* Transparent Mode */
+void TL_LLD_BLE_SendCmd(void)
+{
+ ((TL_CmdPacket_t *)(TL_RefTable.p_lld_ble_table->cmdrsp_buffer))->cmdserial.type = TL_CLICMD_PKT_TYPE;
+ HW_IPCC_LLD_BLE_SendCmd();
+ return;
+}
+
+void HW_IPCC_LLD_BLE_ReceiveRsp(void)
+{
+ TL_LLD_BLE_ReceiveRsp((TL_CmdPacket_t *)(TL_RefTable.p_lld_ble_table->cmdrsp_buffer));
+ return;
+}
+
+void TL_LLD_BLE_SendRspAck(void)
+{
+ HW_IPCC_LLD_BLE_SendRspAck();
+ return;
+}
+#endif /* LLD_BLE_WB */
+
+/******************************************************************************
+ * MEMORY MANAGER
+ ******************************************************************************/
+void TL_MM_Init(TL_MM_Config_t *p_Config)
+{
+ static MB_MemManagerTable_t *p_mem_manager_table;
+
+ LST_init_head(&FreeBufQueue);
+ LST_init_head(&LocalFreeBufQueue);
+
+ p_mem_manager_table = TL_RefTable.p_mem_manager_table;
+
+ p_mem_manager_table->blepool = p_Config->p_AsynchEvtPool;
+ p_mem_manager_table->blepoolsize = p_Config->AsynchEvtPoolSize;
+ p_mem_manager_table->pevt_free_buffer_queue = (uint8_t *)&FreeBufQueue;
+ p_mem_manager_table->spare_ble_buffer = p_Config->p_BleSpareEvtBuffer;
+ p_mem_manager_table->spare_sys_buffer = p_Config->p_SystemSpareEvtBuffer;
+ p_mem_manager_table->traces_evt_pool = p_Config->p_TracesEvtPool;
+ p_mem_manager_table->tracespoolsize = p_Config->TracesEvtPoolSize;
+
+ return;
+}
+
+void TL_MM_EvtDone(TL_EvtPacket_t *phcievt)
+{
+ LST_insert_tail(&LocalFreeBufQueue, (tListNode *)phcievt);
+
+ OutputMemReleaseTrace(phcievt);
+
+ HW_IPCC_MM_SendFreeBuf(SendFreeBuf);
+
+ return;
+}
+
+static void SendFreeBuf(void)
+{
+ tListNode *p_node;
+
+ while (FALSE == LST_is_empty(&LocalFreeBufQueue)) {
+ LST_remove_head(&LocalFreeBufQueue, (tListNode **)&p_node);
+ LST_insert_tail((tListNode *)(TL_RefTable.p_mem_manager_table->pevt_free_buffer_queue), p_node);
+ }
+
+ return;
+}
+
+static void OutputMemReleaseTrace(TL_EvtPacket_t *phcievt)
+{
+ switch (phcievt->evtserial.evt.evtcode) {
+ case TL_BLEEVT_CS_OPCODE:
+ TL_MM_DBG__MSG("mm evt released: 0x%02X", phcievt->evtserial.evt.evtcode);
+ TL_MM_DBG__MSG(" cmd opcode: 0x%04X", ((TL_CsEvt_t *)(phcievt->evtserial.evt.payload))->cmdcode);
+ TL_MM_DBG__MSG(" buffer addr: 0x%08X", phcievt);
+ break;
+
+ case TL_BLEEVT_CC_OPCODE:
+ TL_MM_DBG__MSG("mm evt released: 0x%02X", phcievt->evtserial.evt.evtcode);
+ TL_MM_DBG__MSG(" cmd opcode: 0x%04X", ((TL_CcEvt_t *)(phcievt->evtserial.evt.payload))->cmdcode);
+ TL_MM_DBG__MSG(" buffer addr: 0x%08X", phcievt);
+ break;
+
+ case TL_BLEEVT_VS_OPCODE:
+ TL_MM_DBG__MSG("mm evt released: 0x%02X", phcievt->evtserial.evt.evtcode);
+ TL_MM_DBG__MSG(" subevtcode: 0x%04X", ((TL_AsynchEvt_t *)(phcievt->evtserial.evt.payload))->subevtcode);
+ TL_MM_DBG__MSG(" buffer addr: 0x%08X", phcievt);
+ break;
+
+ default:
+ TL_MM_DBG__MSG("mm evt released: 0x%02X", phcievt->evtserial.evt.evtcode);
+ TL_MM_DBG__MSG(" buffer addr: 0x%08X", phcievt);
+ break;
+ }
+
+ TL_MM_DBG__MSG("\r\n");
+
+ return;
+}
+
+/******************************************************************************
+ * TRACES
+ ******************************************************************************/
+void TL_TRACES_Init(void)
+{
+ LST_init_head(&TracesEvtQueue);
+
+ TL_RefTable.p_traces_table->traces_queue = (uint8_t *)&TracesEvtQueue;
+
+ HW_IPCC_TRACES_Init();
+
+ return;
+}
+
+void HW_IPCC_TRACES_EvtNot(void)
+{
+ TL_EvtPacket_t *phcievt;
+
+ while (LST_is_empty(&TracesEvtQueue) == FALSE) {
+ LST_remove_head(&TracesEvtQueue, (tListNode **)&phcievt);
+ TL_TRACES_EvtReceived(phcievt);
+ }
+
+ return;
+}
+
+__WEAK void TL_TRACES_EvtReceived(TL_EvtPacket_t *hcievt)
+{
+ (void)(hcievt);
+}
+#endif /* STM32WBxx */
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/