Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Flipper-Zero/STM32CubeWB.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'Projects/STM32WB5MM-DK/Applications/BLE/BLE_TransparentMode/STM32_WPAN/App/tm.c')
-rw-r--r--Projects/STM32WB5MM-DK/Applications/BLE/BLE_TransparentMode/STM32_WPAN/App/tm.c552
1 files changed, 552 insertions, 0 deletions
diff --git a/Projects/STM32WB5MM-DK/Applications/BLE/BLE_TransparentMode/STM32_WPAN/App/tm.c b/Projects/STM32WB5MM-DK/Applications/BLE/BLE_TransparentMode/STM32_WPAN/App/tm.c
new file mode 100644
index 000000000..4cd7ca6a0
--- /dev/null
+++ b/Projects/STM32WB5MM-DK/Applications/BLE/BLE_TransparentMode/STM32_WPAN/App/tm.c
@@ -0,0 +1,552 @@
+/* USER CODE BEGIN Header */
+/**
+ ******************************************************************************
+ * File Name : App/tm.c
+ * Description : Transparent mode
+ ******************************************************************************
+ * * @attention
+ *
+ * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
+ * All rights reserved.</center></h2>
+ *
+ * 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
+ *
+
+ ******************************************************************************
+ */
+/* USER CODE END Header */
+
+/* Includes ------------------------------------------------------------------*/
+#include "main.h"
+#include "app_common.h"
+#include "tl.h"
+#include "mbox_def.h"
+#include "lhci.h"
+#include "shci.h"
+#include "stm_list.h"
+#include "tm.h"
+#include "stm32_lpm.h"
+#include "shci_tl.h"
+#include "stm32_seq.h"
+#include "ble_bufsize.h"
+
+/* Private includes ----------------------------------------------------------*/
+/* USER CODE BEGIN Includes */
+
+/* USER CODE END Includes */
+
+/* Private typedef -----------------------------------------------------------*/
+typedef enum
+{
+ LOW_POWER_MODE_DISABLE,
+ LOW_POWER_MODE_ENABLE,
+}LowPowerModeStatus_t;
+
+typedef enum
+{
+ WAITING_TYPE,
+ WAITING_LENGTH,
+ WAITING_PAYLOAD
+}HciReceiveStatus_t;
+
+typedef enum
+{
+ TX_ONGOING,
+ TX_DONE
+}HostTxStatus_t;
+/* USER CODE BEGIN PTD */
+
+/* USER CODE END PTD */
+
+/* Private defines -----------------------------------------------------------*/
+/* USER CODE BEGIN PD */
+
+/* USER CODE END PD */
+
+/* Private macros -------------------------------------------------------------*/
+/* USER CODE BEGIN PM */
+
+/* USER CODE END PM */
+
+/* Private variables ---------------------------------------------------------*/
+PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static TL_CmdPacket_t BleCmdBuffer;
+PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t HciAclDataBuffer[sizeof(TL_PacketHeader_t) + 5 + 251];
+
+static uint8_t RxHostData[5];
+static HciReceiveStatus_t HciReceiveStatus;
+ALIGN(4) static TL_CmdPacket_t SysLocalCmd;
+static uint8_t *pHostRx;
+static tListNode HostTxQueue;
+static TL_EvtPacket_t *pTxToHostPacket;
+static HostTxStatus_t HostTxStatus;
+static MB_RefTable_t * p_RefTable;
+static uint8_t SysLocalCmdStatus;
+static LowPowerModeStatus_t LowPowerModeStatus;
+/* USER CODE BEGIN PV */
+
+/* USER CODE END PV */
+
+/* Private function prototypes -----------------------------------------------*/
+static void RxCpltCallback(void);
+static void HostTxCb( void );
+static void TM_SysLocalCmd( void );
+static void TM_TxToHost( void );
+static void TM_BleEvtRx( TL_EvtPacket_t *phcievt );
+static void TM_AclDataAck( void );
+#if (CFG_HW_LPUART1_ENABLED == 1)
+extern void MX_LPUART1_UART_Init(void);
+#endif
+#if (CFG_HW_USART1_ENABLED == 1)
+extern void MX_USART1_UART_Init(void);
+#endif
+/* USER CODE BEGIN PFP */
+
+/* USER CODE END PFP */
+
+/* Functions Definition ------------------------------------------------------*/
+void TM_Init( void )
+{
+/* USER CODE BEGIN TM_Init_1 */
+ WirelessFwInfo_t wireless_info_instance;
+ WirelessFwInfo_t *p_wireless_info = &wireless_info_instance;
+ char StackVersion[23];
+ char StackBranch[20];
+ char FusVersion[20];
+/* USER CODE END TM_Init_1 */
+ TL_BLE_InitConf_t tl_ble_init_conf;
+ uint32_t ipccdba;
+ 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_OPTIONS,
+ 0,
+ CFG_BLE_MAX_COC_INITIATOR_NBR,
+ CFG_BLE_MIN_TX_POWER,
+ CFG_BLE_MAX_TX_POWER}
+ };
+
+ ipccdba = READ_BIT( FLASH->IPCCBR, FLASH_IPCCBR_IPCCDBA );
+ p_RefTable = (MB_RefTable_t*)((ipccdba<<2) + SRAM2A_BASE);
+
+ tl_ble_init_conf.p_cmdbuffer = (uint8_t*)&BleCmdBuffer;
+ tl_ble_init_conf.p_AclDataBuffer = HciAclDataBuffer;
+ tl_ble_init_conf.IoBusEvtCallBack = TM_BleEvtRx;
+ tl_ble_init_conf.IoBusAclDataTxAck = TM_AclDataAck;
+ TL_BLE_Init( (void*) &tl_ble_init_conf );
+
+ UTIL_LPM_SetOffMode(1 << CFG_LPM_APP_BLE, UTIL_LPM_DISABLE);
+ UTIL_LPM_SetStopMode( 1<<CFG_LPM_APP_BLE, UTIL_LPM_DISABLE);
+ LowPowerModeStatus = LOW_POWER_MODE_DISABLE;
+
+ SysLocalCmdStatus = 0;
+
+ SHCI_C2_BLE_Init( &ble_init_cmd_packet );
+
+ UTIL_SEQ_RegTask( 1<< CFG_TASK_SYS_LOCAL_CMD_ID, UTIL_SEQ_RFU, TM_SysLocalCmd);
+ UTIL_SEQ_RegTask( 1<< CFG_TASK_BLE_HCI_CMD_ID, UTIL_SEQ_RFU, (void (*)( void )) TL_BLE_SendCmd);
+ UTIL_SEQ_RegTask( 1<< CFG_TASK_TX_TO_HOST_ID, UTIL_SEQ_RFU, TM_TxToHost);
+ UTIL_SEQ_RegTask( 1<< CFG_TASK_SYS_HCI_CMD_ID, UTIL_SEQ_RFU, (void (*)( void )) TL_SYS_SendCmd);
+ UTIL_SEQ_RegTask( 1<< CFG_TASK_HCI_ACL_DATA_ID, UTIL_SEQ_RFU, (void (*)( void )) TL_BLE_SendAclData);
+
+ HostTxStatus = TX_DONE;
+ pTxToHostPacket = 0;
+
+ LST_init_head (&HostTxQueue);
+
+ MX_USART1_UART_Init();
+
+ pHostRx = RxHostData;
+ HciReceiveStatus = WAITING_TYPE;
+
+ HW_UART_Receive_IT(CFG_UART_GUI, pHostRx, 1, RxCpltCallback);
+
+/* USER CODE BEGIN TM_Init_2 */
+ /* Displays the board and app informations: Application Name, Stack version, FUS version*/
+ if (SHCI_GetWirelessFwInfo(p_wireless_info) != SHCI_Success)
+ {
+ // Error
+ }
+ else
+ {
+ sprintf(StackVersion, "BLE Stack=v%d.%d.%d", p_wireless_info->VersionMajor, p_wireless_info->VersionMinor, p_wireless_info->VersionSub);
+ sprintf(StackBranch, "Branch=%d Type=%d", p_wireless_info->VersionBranch, p_wireless_info->VersionReleaseType);
+ sprintf(FusVersion, "FUS v%d.%d.%d", p_wireless_info->FusVersionMajor, p_wireless_info->FusVersionMinor, p_wireless_info->FusVersionSub);
+
+ BSP_LCD_Clear(0,SSD1315_COLOR_BLACK);
+ BSP_LCD_Refresh(0);
+ UTIL_LCD_DisplayStringAt(0, 0, (uint8_t *)"ST BLE Transparent Mode", CENTER_MODE);
+ UTIL_LCD_DisplayStringAt(0, LINE(1), (uint8_t *)StackVersion, LEFT_MODE);
+ UTIL_LCD_DisplayStringAt(0, LINE(2), (uint8_t *)StackBranch, LEFT_MODE);
+ UTIL_LCD_DisplayStringAt(0, LINE(3), (uint8_t *)FusVersion, LEFT_MODE);
+ BSP_LCD_Refresh(0);
+ }
+/* USER CODE END TM_Init_2 */
+ return;
+}
+
+void TM_SysCmdRspCb (TL_EvtPacket_t * p_cmd_resp)
+{
+/* USER CODE BEGIN TM_SysCmdRspCb_1 */
+
+/* USER CODE END TM_SysCmdRspCb_1 */
+ if(SysLocalCmdStatus != 0)
+ {
+ SysLocalCmdStatus = 0;
+ UTIL_SEQ_SetEvt( 1<< CFG_IDLEEVT_SYSTEM_HCI_CMD_EVT_RSP_ID );
+ }
+ else
+ {
+ LST_insert_tail (&HostTxQueue, (tListNode *)p_cmd_resp);
+
+ UTIL_SEQ_SetTask( 1<<CFG_TASK_TX_TO_HOST_ID,CFG_SCH_PRIO_0);
+ }
+
+/* USER CODE BEGIN TM_SysCmdRspCb_2 */
+
+/* USER CODE END TM_SysCmdRspCb_2 */
+ return;
+}
+
+/* USER CODE BEGIN FD */
+void TM_SetLowPowerMode( void )
+{
+ aPwmLedGsData_TypeDef aPwmLedGsData;
+ if(LowPowerModeStatus == LOW_POWER_MODE_DISABLE)
+ {
+ LED_Off();
+ LowPowerModeStatus = LOW_POWER_MODE_ENABLE;
+ UTIL_LPM_SetStopMode( 1<<CFG_LPM_APP_BLE, UTIL_LPM_ENABLE);
+ }
+ else
+ {
+ aPwmLedGsData[PWM_LED_RED] = PWM_LED_GSDATA_OFF;
+ aPwmLedGsData[PWM_LED_GREEN] = PWM_LED_GSDATA_7_0;
+ aPwmLedGsData[PWM_LED_BLUE] = PWM_LED_GSDATA_OFF;
+ LED_On(aPwmLedGsData);
+ LowPowerModeStatus = LOW_POWER_MODE_DISABLE;
+ UTIL_LPM_SetStopMode( 1<<CFG_LPM_APP_BLE, UTIL_LPM_DISABLE);
+ }
+ return;
+}
+/* USER CODE END FD */
+
+/*************************************************************
+ *
+ * LOCAL FUNCTIONS
+ *
+ *************************************************************/
+static void TM_TxToHost( void )
+{
+ BACKUP_PRIMASK();
+
+ if(HostTxStatus == TX_DONE)
+ {
+ HostTxStatus = TX_ONGOING;
+
+ LST_remove_head( &HostTxQueue, (tListNode **)&pTxToHostPacket );
+
+ if(LowPowerModeStatus == LOW_POWER_MODE_DISABLE)
+ {
+ if(pTxToHostPacket->evtserial.type == TL_ACL_DATA_PKT_TYPE)
+ {
+ /**
+ * The uart interrupt shall be disable when the HAL is called to send data
+ * This is because in the Rx uart handler, the HAL is called to receive new data
+ */
+ DISABLE_IRQ();
+ HW_UART_Transmit_IT(CFG_UART_GUI, (uint8_t *)&((TL_AclDataPacket_t *)pTxToHostPacket)->AclDataSerial, ((TL_AclDataPacket_t *)pTxToHostPacket)->AclDataSerial.length + 5, HostTxCb);
+ RESTORE_PRIMASK();
+ }
+ else
+ {
+ /**
+ * The uart interrupt shall be disable when the HAL is called to send data
+ * This is because in the Rx uart handler, the HAL is called to receive new data
+ */
+ DISABLE_IRQ();
+ HW_UART_Transmit_IT(CFG_UART_GUI, (uint8_t *)&pTxToHostPacket->evtserial, pTxToHostPacket->evtserial.evt.plen + TL_EVT_HDR_SIZE, HostTxCb);
+ RESTORE_PRIMASK();
+ }
+ }
+ else
+ {
+ HostTxCb( );
+ }
+ }
+
+ return;
+}
+
+static void TM_SysLocalCmd ( void )
+{
+ switch( SysLocalCmd.cmdserial.cmd.cmdcode )
+ {
+ case LHCI_OPCODE_C1_WRITE_REG:
+ LHCI_C1_Write_Register( &SysLocalCmd );
+ break;
+
+ case LHCI_OPCODE_C1_READ_REG:
+ LHCI_C1_Read_Register( &SysLocalCmd );
+ break;
+
+ case LHCI_OPCODE_C1_DEVICE_INF:
+ LHCI_C1_Read_Device_Information( &SysLocalCmd );
+ break;
+
+ default:
+ ((TL_CcEvt_t *)(((TL_EvtPacket_t*)&SysLocalCmd)->evtserial.evt.payload))->cmdcode = SysLocalCmd.cmdserial.cmd.cmdcode;
+ ((TL_CcEvt_t *)(((TL_EvtPacket_t*)&SysLocalCmd)->evtserial.evt.payload))->payload[0] = 0x01;
+ ((TL_CcEvt_t *)(((TL_EvtPacket_t*)&SysLocalCmd)->evtserial.evt.payload))->numcmd = 1;
+ ((TL_EvtPacket_t*)&SysLocalCmd)->evtserial.type = TL_LOCRSP_PKT_TYPE;
+ ((TL_EvtPacket_t*)&SysLocalCmd)->evtserial.evt.evtcode = TL_BLEEVT_CC_OPCODE;
+ ((TL_EvtPacket_t*)&SysLocalCmd)->evtserial.evt.plen = TL_EVT_CS_PAYLOAD_SIZE;
+
+ break;
+ }
+
+ LST_insert_tail (&HostTxQueue, (tListNode *)&SysLocalCmd);
+ UTIL_SEQ_SetTask( 1<<CFG_TASK_TX_TO_HOST_ID,CFG_SCH_PRIO_0);
+
+ return;
+}
+
+static void RxCpltCallback( void )
+{
+ uint16_t nb_bytes_to_receive=0;
+ uint16_t buffer_index=0;
+ uint8_t packet_indicator;
+
+ switch (HciReceiveStatus)
+ {
+ case WAITING_TYPE:
+ {
+ packet_indicator = pHostRx[0];
+ switch(packet_indicator)
+ {
+ case TL_BLECMD_PKT_TYPE:
+ case TL_SYSCMD_PKT_TYPE:
+ case TL_LOCCMD_PKT_TYPE:
+ HciReceiveStatus = WAITING_LENGTH;
+ nb_bytes_to_receive = 3;
+ buffer_index = 1;
+ break;
+
+ case TL_ACL_DATA_PKT_TYPE:
+ HciReceiveStatus = WAITING_LENGTH;
+ nb_bytes_to_receive = 4;
+ buffer_index = 1;
+ break;
+
+ default:
+ nb_bytes_to_receive = 1;
+ buffer_index = 0;
+ break;
+ }
+ }
+ break;
+
+ case WAITING_LENGTH:
+ packet_indicator = pHostRx[0];
+
+ switch( packet_indicator )
+ {
+ case TL_SYSCMD_PKT_TYPE:
+ nb_bytes_to_receive = pHostRx[3];
+ pHostRx = (uint8_t*)&(((TL_CmdPacket_t*)(p_RefTable->p_sys_table->pcmd_buffer))->cmdserial);
+ memcpy(pHostRx, RxHostData, 4);
+ buffer_index = 4;
+ break;
+
+ case TL_LOCCMD_PKT_TYPE:
+ nb_bytes_to_receive = pHostRx[3];
+ pHostRx = (uint8_t*)&SysLocalCmd.cmdserial;
+ memcpy(pHostRx, RxHostData, 4);
+ buffer_index = 4;
+ break;
+
+ case TL_ACL_DATA_PKT_TYPE:
+ nb_bytes_to_receive = pHostRx[3] + (pHostRx[4] << 8);
+ pHostRx = (uint8_t*)&(((TL_AclDataPacket_t*)(p_RefTable->p_ble_table->phci_acl_data_buffer))->AclDataSerial);
+ memcpy(pHostRx, RxHostData, 5);
+ buffer_index = 5;
+ break;
+
+ default:
+ nb_bytes_to_receive = pHostRx[3];
+ pHostRx = (uint8_t*)&(((TL_CmdPacket_t*)(p_RefTable->p_ble_table->pcmd_buffer))->cmdserial);
+ memcpy(pHostRx, RxHostData, 4);
+ buffer_index = 4;
+ break;
+ }
+
+ if(nb_bytes_to_receive)
+ {
+ HciReceiveStatus = WAITING_PAYLOAD;
+ }
+ else
+ {
+ switch ( packet_indicator )
+ {
+ case TL_SYSCMD_PKT_TYPE:
+ UTIL_SEQ_SetTask( 1<<CFG_TASK_SYS_HCI_CMD_ID,CFG_SCH_PRIO_0);
+ break;
+
+ case TL_LOCCMD_PKT_TYPE:
+ UTIL_SEQ_SetTask( 1<<CFG_TASK_SYS_LOCAL_CMD_ID,CFG_SCH_PRIO_0);
+ break;
+
+ case TL_ACL_DATA_PKT_TYPE:
+ UTIL_SEQ_SetTask( 1<<CFG_TASK_HCI_ACL_DATA_ID,CFG_SCH_PRIO_0);
+ break;
+
+ default:
+ UTIL_SEQ_SetTask( 1<<CFG_TASK_BLE_HCI_CMD_ID,CFG_SCH_PRIO_0);
+ break;
+ }
+
+ HciReceiveStatus = WAITING_TYPE;
+ nb_bytes_to_receive = 1;
+ buffer_index = 0;
+ pHostRx = RxHostData;
+ }
+ break;
+
+ case WAITING_PAYLOAD:
+ packet_indicator = pHostRx[0];
+
+ switch ( packet_indicator )
+ {
+ case TL_SYSCMD_PKT_TYPE:
+ UTIL_SEQ_SetTask( 1<<CFG_TASK_SYS_HCI_CMD_ID,CFG_SCH_PRIO_0);
+ break;
+
+ case TL_LOCCMD_PKT_TYPE:
+ UTIL_SEQ_SetTask( 1<<CFG_TASK_SYS_LOCAL_CMD_ID,CFG_SCH_PRIO_0);
+ break;
+
+ case TL_ACL_DATA_PKT_TYPE:
+ UTIL_SEQ_SetTask( 1<<CFG_TASK_HCI_ACL_DATA_ID,CFG_SCH_PRIO_0);
+ break;
+
+ default:
+ UTIL_SEQ_SetTask( 1<<CFG_TASK_BLE_HCI_CMD_ID,CFG_SCH_PRIO_0);
+ break;
+ }
+
+ HciReceiveStatus = WAITING_TYPE;
+ nb_bytes_to_receive = 1;
+ buffer_index = 0;
+ pHostRx = RxHostData;
+
+ break;
+
+ default:
+ break;
+ }
+
+ HW_UART_Receive_IT(CFG_UART_GUI, &pHostRx[buffer_index], nb_bytes_to_receive, RxCpltCallback);
+
+ return;
+}
+
+static void HostTxCb( void )
+{
+ HostTxStatus = TX_DONE;
+
+ if( (pTxToHostPacket >= (TL_EvtPacket_t *)(p_RefTable->p_mem_manager_table->blepool)) && (pTxToHostPacket < ( (TL_EvtPacket_t *)((p_RefTable->p_mem_manager_table->blepool) + p_RefTable->p_mem_manager_table->blepoolsize))))
+ {
+ TL_MM_EvtDone(pTxToHostPacket);
+ }
+
+ if ( LST_is_empty( &HostTxQueue ) == FALSE )
+ {
+ UTIL_SEQ_SetTask( 1<<CFG_TASK_TX_TO_HOST_ID,CFG_SCH_PRIO_0 );
+ }
+
+ return;
+}
+
+static void TM_BleEvtRx( TL_EvtPacket_t *phcievt )
+{
+ LST_insert_tail ( &HostTxQueue, (tListNode *)phcievt );
+
+ UTIL_SEQ_SetTask( 1<<CFG_TASK_TX_TO_HOST_ID,CFG_SCH_PRIO_0 );
+
+ return;
+}
+
+static void TM_AclDataAck( void )
+{
+ /**
+ * The current implementation assumes the GUI 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 GUI
+ * - a local pool of buffer to store packets received from the GUI
+ */
+ return;
+}
+
+/* USER CODE BEGIN FD_LOCAL_FUNCTIONS*/
+
+/* USER CODE END FD_LOCAL_FUNCTIONS*/
+/*************************************************************
+ *
+ * WRAP FUNCTIONS
+ *
+ *************************************************************/
+void shci_send( uint16_t cmd_code, uint8_t len_cmd_payload, uint8_t * p_cmd_payload, TL_EvtPacket_t * p_rsp_status )
+{
+ TL_CmdPacket_t *p_cmd_buffer;
+ uint32_t ipccdba;
+ MB_RefTable_t * p_ref_table;
+
+ ipccdba = READ_BIT( FLASH->IPCCBR, FLASH_IPCCBR_IPCCDBA );
+ p_ref_table = (MB_RefTable_t*)((ipccdba<<2) + SRAM2A_BASE);
+
+ SysLocalCmdStatus = 1;
+
+ p_cmd_buffer = (TL_CmdPacket_t *)(p_ref_table->p_sys_table->pcmd_buffer);
+
+ p_cmd_buffer->cmdserial.cmd.cmdcode = cmd_code;
+ p_cmd_buffer->cmdserial.cmd.plen = len_cmd_payload;
+
+ memcpy(p_cmd_buffer->cmdserial.cmd.payload, p_cmd_payload, len_cmd_payload );
+
+ TL_SYS_SendCmd( 0, 0 );
+
+ UTIL_SEQ_WaitEvt( 1<< CFG_IDLEEVT_SYSTEM_HCI_CMD_EVT_RSP_ID );
+
+ /**
+ * The command complete of a system command does not have the header
+ * It starts immediately with the evtserial field
+ */
+ memcpy( &(p_rsp_status->evtserial), p_cmd_buffer, ((TL_EvtSerial_t*)p_cmd_buffer)->evt.plen + TL_EVT_HDR_SIZE );
+
+ return;
+}
+
+/* USER CODE BEGIN FD_WRAP_FUNCTIONS*/
+
+/* USER CODE END FD_WRAP_FUNCTIONS*/
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/