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****/