Naming and coding style convention, new linter tool. (#945)
* Makefile, Scripts: new linter * About: remove ID from IC * Firmware: remove double define for DIVC/DIVR * Scripts: check folder names too. Docker: replace syntax check with make lint. * Reformat Sources and Migrate to new file naming convention * Docker: symlink clang-format-12 to clang-format * Add coding style guide
This commit is contained in:
39
firmware/targets/f6/ble_glue/app_common.h
Normal file
39
firmware/targets/f6/ble_glue/app_common.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : app_common.h
|
||||
* Description : App Common application configuration file for STM32WPAN Middleware.
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2020 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 */
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef APP_COMMON_H
|
||||
#define APP_COMMON_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <furi/common_defines.h>
|
||||
|
||||
#include "app_conf.h"
|
||||
|
||||
#endif
|
||||
465
firmware/targets/f6/ble_glue/app_conf.h
Normal file
465
firmware/targets/f6/ble_glue/app_conf.h
Normal file
@@ -0,0 +1,465 @@
|
||||
#pragma once
|
||||
|
||||
#include "hw.h"
|
||||
#include "hw_conf.h"
|
||||
#include "hw_if.h"
|
||||
#include "ble_bufsize.h"
|
||||
|
||||
#define CFG_TX_POWER (0x19) /* +0dBm */
|
||||
|
||||
/**
|
||||
* Define Advertising parameters
|
||||
*/
|
||||
#define CFG_ADV_BD_ADDRESS (0x7257acd87a6c)
|
||||
#define CFG_FAST_CONN_ADV_INTERVAL_MIN (0x80) /**< 80ms */
|
||||
#define CFG_FAST_CONN_ADV_INTERVAL_MAX (0xa0) /**< 100ms */
|
||||
#define CFG_LP_CONN_ADV_INTERVAL_MIN (0x640) /**< 1s */
|
||||
#define CFG_LP_CONN_ADV_INTERVAL_MAX (0xfa0) /**< 2.5s */
|
||||
|
||||
/**
|
||||
* Define IO Authentication
|
||||
*/
|
||||
#define CFG_BONDING_MODE (1)
|
||||
#define CFG_FIXED_PIN (111111)
|
||||
#define CFG_USED_FIXED_PIN (1)
|
||||
#define CFG_ENCRYPTION_KEY_SIZE_MAX (16)
|
||||
#define CFG_ENCRYPTION_KEY_SIZE_MIN (8)
|
||||
|
||||
/**
|
||||
* Define IO capabilities
|
||||
*/
|
||||
#define CFG_IO_CAPABILITY_DISPLAY_ONLY (0x00)
|
||||
#define CFG_IO_CAPABILITY_DISPLAY_YES_NO (0x01)
|
||||
#define CFG_IO_CAPABILITY_KEYBOARD_ONLY (0x02)
|
||||
#define CFG_IO_CAPABILITY_NO_INPUT_NO_OUTPUT (0x03)
|
||||
#define CFG_IO_CAPABILITY_KEYBOARD_DISPLAY (0x04)
|
||||
|
||||
#define CFG_IO_CAPABILITY CFG_IO_CAPABILITY_DISPLAY_YES_NO
|
||||
|
||||
/**
|
||||
* Define MITM modes
|
||||
*/
|
||||
#define CFG_MITM_PROTECTION_NOT_REQUIRED (0x00)
|
||||
#define CFG_MITM_PROTECTION_REQUIRED (0x01)
|
||||
|
||||
#define CFG_MITM_PROTECTION CFG_MITM_PROTECTION_REQUIRED
|
||||
|
||||
/**
|
||||
* Define Secure Connections Support
|
||||
*/
|
||||
#define CFG_SECURE_NOT_SUPPORTED (0x00)
|
||||
#define CFG_SECURE_OPTIONAL (0x01)
|
||||
#define CFG_SECURE_MANDATORY (0x02)
|
||||
|
||||
#define CFG_SC_SUPPORT CFG_SECURE_OPTIONAL
|
||||
|
||||
/**
|
||||
* Define Keypress Notification Support
|
||||
*/
|
||||
#define CFG_KEYPRESS_NOT_SUPPORTED (0x00)
|
||||
#define CFG_KEYPRESS_SUPPORTED (0x01)
|
||||
|
||||
#define CFG_KEYPRESS_NOTIFICATION_SUPPORT CFG_KEYPRESS_NOT_SUPPORTED
|
||||
|
||||
/**
|
||||
* Numeric Comparison Answers
|
||||
*/
|
||||
#define YES (0x01)
|
||||
#define NO (0x00)
|
||||
|
||||
/**
|
||||
* Device name configuration for Generic Access Service
|
||||
*/
|
||||
#define CFG_GAP_DEVICE_NAME "TEMPLATE"
|
||||
#define CFG_GAP_DEVICE_NAME_LENGTH (8)
|
||||
|
||||
/**
|
||||
* Define PHY
|
||||
*/
|
||||
#define ALL_PHYS_PREFERENCE 0x00
|
||||
#define RX_2M_PREFERRED 0x02
|
||||
#define TX_2M_PREFERRED 0x02
|
||||
#define TX_1M 0x01
|
||||
#define TX_2M 0x02
|
||||
#define RX_1M 0x01
|
||||
#define RX_2M 0x02
|
||||
|
||||
/**
|
||||
* Identity root key used to derive LTK and CSRK
|
||||
*/
|
||||
#define CFG_BLE_IRK \
|
||||
{ \
|
||||
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, \
|
||||
0xf0 \
|
||||
}
|
||||
|
||||
/**
|
||||
* Encryption root key used to derive LTK and CSRK
|
||||
*/
|
||||
#define CFG_BLE_ERK \
|
||||
{ \
|
||||
0xfe, 0xdc, 0xba, 0x09, 0x87, 0x65, 0x43, 0x21, 0xfe, 0xdc, 0xba, 0x09, 0x87, 0x65, 0x43, \
|
||||
0x21 \
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN Generic_Parameters */
|
||||
/**
|
||||
* SMPS supply
|
||||
* SMPS not used when Set to 0
|
||||
* SMPS used when Set to 1
|
||||
*/
|
||||
#define CFG_USE_SMPS 1
|
||||
/* USER CODE END Generic_Parameters */
|
||||
|
||||
/**< specific parameters */
|
||||
/*****************************************************/
|
||||
|
||||
/**
|
||||
* AD Element - Group B Feature
|
||||
*/
|
||||
/* LSB - Second Byte */
|
||||
#define CFG_FEATURE_OTA_REBOOT (0x20)
|
||||
|
||||
/******************************************************************************
|
||||
* BLE Stack
|
||||
******************************************************************************/
|
||||
/**
|
||||
* Maximum number of simultaneous connections that the device will support.
|
||||
* Valid values are from 1 to 8
|
||||
*/
|
||||
#define CFG_BLE_NUM_LINK 2
|
||||
|
||||
/**
|
||||
* 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 (256 + 128 + 16 + 8 + 4 + 2)
|
||||
|
||||
/**
|
||||
* 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)
|
||||
|
||||
/**
|
||||
* 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))
|
||||
|
||||
/**
|
||||
* 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 low speed clock for RF wake-up
|
||||
* 1 : external high speed crystal HSE/32/32
|
||||
* 0 : external low speed 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
|
||||
|
||||
/**
|
||||
* BLE stack Options flags to be configured with:
|
||||
* - SHCI_C2_BLE_INIT_OPTIONS_LL_ONLY
|
||||
* - SHCI_C2_BLE_INIT_OPTIONS_LL_HOST
|
||||
* - SHCI_C2_BLE_INIT_OPTIONS_NO_SVC_CHANGE_DESC
|
||||
* - SHCI_C2_BLE_INIT_OPTIONS_WITH_SVC_CHANGE_DESC
|
||||
* - SHCI_C2_BLE_INIT_OPTIONS_DEVICE_NAME_RO
|
||||
* - SHCI_C2_BLE_INIT_OPTIONS_DEVICE_NAME_RW
|
||||
* - SHCI_C2_BLE_INIT_OPTIONS_EXT_ADV
|
||||
* - SHCI_C2_BLE_INIT_OPTIONS_NO_EXT_ADV
|
||||
* - SHCI_C2_BLE_INIT_OPTIONS_CS_ALGO2
|
||||
* - SHCI_C2_BLE_INIT_OPTIONS_NO_CS_ALGO2
|
||||
* - SHCI_C2_BLE_INIT_OPTIONS_POWER_CLASS_1
|
||||
* - SHCI_C2_BLE_INIT_OPTIONS_POWER_CLASS_2_3
|
||||
* which are used to set following configuration bits:
|
||||
* (bit 0): 1: LL only
|
||||
* 0: LL + host
|
||||
* (bit 1): 1: no service change desc.
|
||||
* 0: with service change desc.
|
||||
* (bit 2): 1: device name Read-Only
|
||||
* 0: device name R/W
|
||||
* (bit 3): 1: extended advertizing supported [NOT SUPPORTED]
|
||||
* 0: extended advertizing not supported [NOT SUPPORTED]
|
||||
* (bit 4): 1: CS Algo #2 supported
|
||||
* 0: CS Algo #2 not supported
|
||||
* (bit 7): 1: LE Power Class 1
|
||||
* 0: LE Power Class 2-3
|
||||
* other bits: reserved (shall be set to 0)
|
||||
*/
|
||||
#define CFG_BLE_OPTIONS \
|
||||
(SHCI_C2_BLE_INIT_OPTIONS_LL_HOST | SHCI_C2_BLE_INIT_OPTIONS_WITH_SVC_CHANGE_DESC | \
|
||||
SHCI_C2_BLE_INIT_OPTIONS_DEVICE_NAME_RW | SHCI_C2_BLE_INIT_OPTIONS_NO_EXT_ADV | \
|
||||
SHCI_C2_BLE_INIT_OPTIONS_NO_CS_ALGO2 | SHCI_C2_BLE_INIT_OPTIONS_POWER_CLASS_2_3)
|
||||
|
||||
/**
|
||||
* Queue length of BLE Event
|
||||
* This parameter defines the number of asynchronous events that can be stored in the HCI layer before
|
||||
* being reported to the application. When a command is sent to the BLE core coprocessor, the HCI layer
|
||||
* is waiting for the event with the Num_HCI_Command_Packets set to 1. The receive queue shall be large
|
||||
* enough to store all asynchronous events received in between.
|
||||
* When CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE is set to 27, this allow to store three 255 bytes long asynchronous events
|
||||
* between the HCI command and its event.
|
||||
* This parameter depends on the value given to CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE. When the queue size is to small,
|
||||
* the system may hang if the queue is full with asynchronous events and the HCI layer is still waiting
|
||||
* for a CC/CS event, In that case, the notification TL_BLE_HCI_ToNot() is called to indicate
|
||||
* to the application a HCI command did not receive its command event within 30s (Default HCI Timeout).
|
||||
*/
|
||||
#define CFG_TLBLE_EVT_QUEUE_LENGTH 5
|
||||
/**
|
||||
* This parameter should be set to fit most events received by the HCI layer. It defines the buffer size of each element
|
||||
* allocated in the queue of received events and can be used to optimize the amount of RAM allocated by the Memory Manager.
|
||||
* It should not exceed 255 which is the maximum HCI packet payload size (a greater value is a lost of memory as it will
|
||||
* never be used)
|
||||
* With the current wireless firmware implementation, this parameter shall be kept to 255
|
||||
*
|
||||
*/
|
||||
#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)
|
||||
/******************************************************************************
|
||||
* UART interfaces
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* Select UART interfaces
|
||||
*/
|
||||
#define CFG_DEBUG_TRACE_UART hw_uart1
|
||||
#define CFG_CONSOLE_MENU 0
|
||||
|
||||
/******************************************************************************
|
||||
* Low Power
|
||||
******************************************************************************/
|
||||
/**
|
||||
* When set to 1, the low power mode is enable
|
||||
* When set to 0, the device stays in RUN mode
|
||||
*/
|
||||
#define CFG_LPM_SUPPORTED 1
|
||||
|
||||
/******************************************************************************
|
||||
* Timer Server
|
||||
******************************************************************************/
|
||||
/**
|
||||
* CFG_RTC_WUCKSEL_DIVIDER: This sets the RTCCLK divider to the wakeup timer.
|
||||
* The lower is the value, the better is the power consumption and the accuracy of the timerserver
|
||||
* The higher is the value, the finest is the granularity
|
||||
*
|
||||
* CFG_RTC_ASYNCH_PRESCALER: This sets the asynchronous prescaler of the RTC. It should as high as possible ( to ouput
|
||||
* clock as low as possible) but the output clock should be equal or higher frequency compare to the clock feeding
|
||||
* the wakeup timer. A lower clock speed would impact the accuracy of the timer server.
|
||||
*
|
||||
* CFG_RTC_SYNCH_PRESCALER: This sets the synchronous prescaler of the RTC.
|
||||
* When the 1Hz calendar clock is required, it shall be sets according to other settings
|
||||
* When the 1Hz calendar clock is not needed, CFG_RTC_SYNCH_PRESCALER should be set to 0x7FFF (MAX VALUE)
|
||||
*
|
||||
* CFG_RTCCLK_DIVIDER_CONF:
|
||||
* Shall be set to either 0,2,4,8,16
|
||||
* When set to either 2,4,8,16, the 1Hhz calendar is supported
|
||||
* When set to 0, the user sets its own configuration
|
||||
*
|
||||
* The following settings are computed with LSI as input to the RTC
|
||||
*/
|
||||
#define CFG_RTCCLK_DIVIDER_CONF 0
|
||||
|
||||
#if(CFG_RTCCLK_DIVIDER_CONF == 0)
|
||||
/**
|
||||
* Custom configuration
|
||||
* It does not support 1Hz calendar
|
||||
* It divides the RTC CLK by 16
|
||||
*/
|
||||
#define CFG_RTCCLK_DIV (16)
|
||||
#define CFG_RTC_WUCKSEL_DIVIDER (0)
|
||||
#define CFG_RTC_ASYNCH_PRESCALER (CFG_RTCCLK_DIV - 1)
|
||||
#define CFG_RTC_SYNCH_PRESCALER (0x7FFF)
|
||||
|
||||
#else
|
||||
|
||||
#if(CFG_RTCCLK_DIVIDER_CONF == 2)
|
||||
/**
|
||||
* It divides the RTC CLK by 2
|
||||
*/
|
||||
#define CFG_RTC_WUCKSEL_DIVIDER (3)
|
||||
#endif
|
||||
|
||||
#if(CFG_RTCCLK_DIVIDER_CONF == 4)
|
||||
/**
|
||||
* It divides the RTC CLK by 4
|
||||
*/
|
||||
#define CFG_RTC_WUCKSEL_DIVIDER (2)
|
||||
#endif
|
||||
|
||||
#if(CFG_RTCCLK_DIVIDER_CONF == 8)
|
||||
/**
|
||||
* It divides the RTC CLK by 8
|
||||
*/
|
||||
#define CFG_RTC_WUCKSEL_DIVIDER (1)
|
||||
#endif
|
||||
|
||||
#if(CFG_RTCCLK_DIVIDER_CONF == 16)
|
||||
/**
|
||||
* It divides the RTC CLK by 16
|
||||
*/
|
||||
#define CFG_RTC_WUCKSEL_DIVIDER (0)
|
||||
#endif
|
||||
|
||||
#define CFG_RTCCLK_DIV CFG_RTCCLK_DIVIDER_CONF
|
||||
#define CFG_RTC_ASYNCH_PRESCALER (CFG_RTCCLK_DIV - 1)
|
||||
#define CFG_RTC_SYNCH_PRESCALER (DIVR(LSE_VALUE, (CFG_RTC_ASYNCH_PRESCALER + 1)) - 1)
|
||||
|
||||
#endif
|
||||
|
||||
/** tick timer value in us */
|
||||
#define CFG_TS_TICK_VAL DIVR((CFG_RTCCLK_DIV * 1000000), LSE_VALUE)
|
||||
|
||||
typedef enum {
|
||||
CFG_TIM_PROC_ID_ISR,
|
||||
/* USER CODE BEGIN CFG_TimProcID_t */
|
||||
|
||||
/* USER CODE END CFG_TimProcID_t */
|
||||
} CFG_TimProcID_t;
|
||||
|
||||
/******************************************************************************
|
||||
* Debug
|
||||
******************************************************************************/
|
||||
/**
|
||||
* When set, this resets some hw resources to set the device in the same state than the power up
|
||||
* The FW resets only register that may prevent the FW to run properly
|
||||
*
|
||||
* This shall be set to 0 in a final product
|
||||
*
|
||||
*/
|
||||
#define CFG_HW_RESET_BY_FW 0
|
||||
|
||||
/**
|
||||
* keep debugger enabled while in any low power mode when set to 1
|
||||
* should be set to 0 in production
|
||||
*/
|
||||
#define CFG_DEBUGGER_SUPPORTED 0
|
||||
|
||||
/**
|
||||
* When set to 1, the traces are enabled in the BLE services
|
||||
*/
|
||||
#define CFG_DEBUG_BLE_TRACE 0
|
||||
|
||||
/**
|
||||
* Enable or Disable traces in application
|
||||
*/
|
||||
#define CFG_DEBUG_APP_TRACE 0
|
||||
|
||||
#if(CFG_DEBUG_APP_TRACE != 0)
|
||||
#define APP_DBG_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define APP_DBG_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if((CFG_DEBUG_BLE_TRACE != 0) || (CFG_DEBUG_APP_TRACE != 0))
|
||||
#define CFG_DEBUG_TRACE 1
|
||||
#endif
|
||||
|
||||
#if(CFG_DEBUG_TRACE != 0)
|
||||
#undef CFG_LPM_SUPPORTED
|
||||
#undef CFG_DEBUGGER_SUPPORTED
|
||||
#define CFG_LPM_SUPPORTED 0
|
||||
#define CFG_DEBUGGER_SUPPORTED 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* When CFG_DEBUG_TRACE_FULL is set to 1, the trace are output with the API name, the file name and the line number
|
||||
* When CFG_DEBUG_TRACE_LIGHT is set to 1, only the debug message is output
|
||||
*
|
||||
* When both are set to 0, no trace are output
|
||||
* When both are set to 1, CFG_DEBUG_TRACE_FULL is selected
|
||||
*/
|
||||
#define CFG_DEBUG_TRACE_LIGHT 0
|
||||
#define CFG_DEBUG_TRACE_FULL 0
|
||||
|
||||
#if((CFG_DEBUG_TRACE != 0) && (CFG_DEBUG_TRACE_LIGHT == 0) && (CFG_DEBUG_TRACE_FULL == 0))
|
||||
#undef CFG_DEBUG_TRACE_FULL
|
||||
#undef CFG_DEBUG_TRACE_LIGHT
|
||||
#define CFG_DEBUG_TRACE_FULL 0
|
||||
#define CFG_DEBUG_TRACE_LIGHT 1
|
||||
#endif
|
||||
|
||||
#if(CFG_DEBUG_TRACE == 0)
|
||||
#undef CFG_DEBUG_TRACE_FULL
|
||||
#undef CFG_DEBUG_TRACE_LIGHT
|
||||
#define CFG_DEBUG_TRACE_FULL 0
|
||||
#define CFG_DEBUG_TRACE_LIGHT 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* When not set, the traces is looping on sending the trace over UART
|
||||
*/
|
||||
#define DBG_TRACE_USE_CIRCULAR_QUEUE 0
|
||||
|
||||
/**
|
||||
* max buffer Size to queue data traces and max data trace allowed.
|
||||
* Only Used if DBG_TRACE_USE_CIRCULAR_QUEUE is defined
|
||||
*/
|
||||
#define DBG_TRACE_MSG_QUEUE_SIZE 4096
|
||||
#define MAX_DBG_TRACE_MSG_SIZE 1024
|
||||
|
||||
#define CFG_OTP_BASE_ADDRESS OTP_AREA_BASE
|
||||
#define CFG_OTP_END_ADRESS OTP_AREA_END_ADDR
|
||||
357
firmware/targets/f6/ble_glue/app_debug.c
Normal file
357
firmware/targets/f6/ble_glue/app_debug.c
Normal file
@@ -0,0 +1,357 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : app_debug.c
|
||||
* Description : Debug capabilities source file for STM32WPAN Middleware
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2020 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 ------------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
#include "utilities_common.h"
|
||||
|
||||
#include "app_common.h"
|
||||
#include "app_debug.h"
|
||||
#include "shci.h"
|
||||
#include "tl.h"
|
||||
#include "dbg_trace.h"
|
||||
#include <furi_hal.h>
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PTD */
|
||||
typedef PACKED_STRUCT {
|
||||
GPIO_TypeDef* port;
|
||||
uint16_t pin;
|
||||
uint8_t enable;
|
||||
uint8_t reserved;
|
||||
}
|
||||
APPD_GpioConfig_t;
|
||||
/* USER CODE END PTD */
|
||||
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PD */
|
||||
#define GPIO_NBR_OF_RF_SIGNALS 9
|
||||
#define GPIO_CFG_NBR_OF_FEATURES 34
|
||||
#define NBR_OF_TRACES_CONFIG_PARAMETERS 4
|
||||
#define NBR_OF_GENERAL_CONFIG_PARAMETERS 4
|
||||
|
||||
/**
|
||||
* THIS SHALL BE SET TO A VALUE DIFFERENT FROM 0 ONLY ON REQUEST FROM ST SUPPORT
|
||||
*/
|
||||
#define BLE_DTB_CFG 7
|
||||
#define SYS_DBG_CFG1 (SHCI_C2_DEBUG_OPTIONS_IPCORE_LP | SHCI_C2_DEBUG_OPTIONS_CPU2_STOP_EN)
|
||||
/* USER CODE END PD */
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PV */
|
||||
PLACE_IN_SECTION("MB_MEM2")
|
||||
ALIGN(4) static SHCI_C2_DEBUG_TracesConfig_t APPD_TracesConfig = {0, 0, 0, 0};
|
||||
PLACE_IN_SECTION("MB_MEM2")
|
||||
ALIGN(4)
|
||||
static SHCI_C2_DEBUG_GeneralConfig_t APPD_GeneralConfig = {BLE_DTB_CFG, SYS_DBG_CFG1, {0, 0}};
|
||||
|
||||
/**
|
||||
* THE DEBUG ON GPIO FOR CPU2 IS INTENDED TO BE USED ONLY ON REQUEST FROM ST SUPPORT
|
||||
* It provides timing information on the CPU2 activity.
|
||||
* All configuration of (port, pin) is supported for each features and can be selected by the user
|
||||
* depending on the availability
|
||||
*/
|
||||
static const APPD_GpioConfig_t aGpioConfigList[GPIO_CFG_NBR_OF_FEATURES] = {
|
||||
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* BLE_ISR - Set on Entry / Reset on Exit */
|
||||
{GPIOA, LL_GPIO_PIN_7, 1, 0}, /* BLE_STACK_TICK - Set on Entry / Reset on Exit */
|
||||
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* BLE_CMD_PROCESS - Set on Entry / Reset on Exit */
|
||||
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* BLE_ACL_DATA_PROCESS - Set on Entry / Reset on Exit */
|
||||
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* SYS_CMD_PROCESS - Set on Entry / Reset on Exit */
|
||||
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* RNG_PROCESS - Set on Entry / Reset on Exit */
|
||||
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* NVM_PROCESS - Set on Entry / Reset on Exit */
|
||||
{GPIOB, LL_GPIO_PIN_3, 1, 0}, /* IPCC_GENERAL - Set on Entry / Reset on Exit */
|
||||
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_BLE_CMD_RX - Set on Entry / Reset on Exit */
|
||||
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_BLE_EVT_TX - Set on Entry / Reset on Exit */
|
||||
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_BLE_ACL_DATA_RX - Set on Entry / Reset on Exit */
|
||||
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_SYS_CMD_RX - Set on Entry / Reset on Exit */
|
||||
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_SYS_EVT_TX - Set on Entry / Reset on Exit */
|
||||
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_CLI_CMD_RX - Set on Entry / Reset on Exit */
|
||||
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_OT_CMD_RX - Set on Entry / Reset on Exit */
|
||||
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_OT_ACK_TX - Set on Entry / Reset on Exit */
|
||||
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_CLI_ACK_TX - Set on Entry / Reset on Exit */
|
||||
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_MEM_MANAGER_RX - Set on Entry / Reset on Exit */
|
||||
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_TRACES_TX - Set on Entry / Reset on Exit */
|
||||
{GPIOA, LL_GPIO_PIN_6, 1, 0}, /* HARD_FAULT - Set on Entry / Reset on Exit */
|
||||
/* From v1.1.1 */
|
||||
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IP_CORE_LP_STATUS - Set on Entry / Reset on Exit */
|
||||
/* From v1.2.0 */
|
||||
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* END_OF_CONNECTION_EVENT - Set on Entry / Reset on Exit */
|
||||
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* TIMER_SERVER_CALLBACK - Toggle on Entry */
|
||||
{GPIOA, LL_GPIO_PIN_4, 1, 0}, /* PES_ACTIVITY - Set on Entry / Reset on Exit */
|
||||
{GPIOB, LL_GPIO_PIN_2, 1, 0}, /* MB_BLE_SEND_EVT - Set on Entry / Reset on Exit */
|
||||
/* From v1.3.0 */
|
||||
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* BLE_NO_DELAY - Set on Entry / Reset on Exit */
|
||||
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* BLE_STACK_STORE_NVM_CB - Set on Entry / Reset on Exit */
|
||||
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* NVMA_WRITE_ONGOING - Set on Entry / Reset on Exit */
|
||||
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* NVMA_WRITE_COMPLETE - Set on Entry / Reset on Exit */
|
||||
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* NVMA_CLEANUP - Set on Entry / Reset on Exit */
|
||||
/* From v1.4.0 */
|
||||
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* NVMA_START - Set on Entry / Reset on Exit */
|
||||
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* FLASH_EOP - Set on Entry / Reset on Exit */
|
||||
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* FLASH_WRITE - Set on Entry / Reset on Exit */
|
||||
{GPIOA, LL_GPIO_PIN_0, 0, 0}, /* FLASH_ERASE - Set on Entry / Reset on Exit */
|
||||
};
|
||||
|
||||
/**
|
||||
* THE DEBUG ON GPIO FOR CPU2 IS INTENDED TO BE USED ONLY ON REQUEST FROM ST SUPPORT
|
||||
* This table is relevant only for BLE
|
||||
* It provides timing information on BLE RF activity.
|
||||
* New signals may be allocated at any location when requested by ST
|
||||
* The GPIO allocated to each signal depend on the BLE_DTB_CFG value and cannot be changed
|
||||
*/
|
||||
#if(BLE_DTB_CFG == 7)
|
||||
static const APPD_GpioConfig_t aRfConfigList[GPIO_NBR_OF_RF_SIGNALS] = {
|
||||
{GPIOB, LL_GPIO_PIN_2, 0, 0}, /* DTB10 - Tx/Rx SPI */
|
||||
{GPIOB, LL_GPIO_PIN_7, 0, 0}, /* DTB11 - Tx/Tx SPI Clk */
|
||||
{GPIOA, LL_GPIO_PIN_8, 0, 0}, /* DTB12 - Tx/Rx Ready & SPI Select */
|
||||
{GPIOA, LL_GPIO_PIN_9, 0, 0}, /* DTB13 - Tx/Rx Start */
|
||||
{GPIOA, LL_GPIO_PIN_10, 0, 0}, /* DTB14 - FSM0 */
|
||||
{GPIOA, LL_GPIO_PIN_11, 0, 0}, /* DTB15 - FSM1 */
|
||||
{GPIOB, LL_GPIO_PIN_8, 0, 0}, /* DTB16 - FSM2 */
|
||||
{GPIOB, LL_GPIO_PIN_11, 0, 0}, /* DTB17 - FSM3 */
|
||||
{GPIOB, LL_GPIO_PIN_10, 0, 0}, /* DTB18 - FSM4 */
|
||||
};
|
||||
#endif
|
||||
/* USER CODE END PV */
|
||||
|
||||
/* Global variables ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN GV */
|
||||
/* USER CODE END GV */
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* USER CODE BEGIN PFP */
|
||||
static void APPD_SetCPU2GpioConfig(void);
|
||||
static void APPD_BleDtbCfg(void);
|
||||
/* USER CODE END PFP */
|
||||
|
||||
/* Functions Definition ------------------------------------------------------*/
|
||||
void APPD_Init(void) {
|
||||
/* USER CODE BEGIN APPD_Init */
|
||||
#if(CFG_DEBUGGER_SUPPORTED == 1)
|
||||
/**
|
||||
* Keep debugger enabled while in any low power mode
|
||||
*/
|
||||
HAL_DBGMCU_EnableDBGSleepMode();
|
||||
HAL_DBGMCU_EnableDBGStopMode();
|
||||
|
||||
/***************** ENABLE DEBUGGER *************************************/
|
||||
LL_EXTI_EnableIT_32_63(LL_EXTI_LINE_48);
|
||||
|
||||
#else
|
||||
GPIO_InitTypeDef gpio_config = {0};
|
||||
|
||||
gpio_config.Pull = GPIO_NOPULL;
|
||||
gpio_config.Mode = GPIO_MODE_ANALOG;
|
||||
|
||||
gpio_config.Pin = GPIO_PIN_15 | GPIO_PIN_14 | GPIO_PIN_13;
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
HAL_GPIO_Init(GPIOA, &gpio_config);
|
||||
__HAL_RCC_GPIOA_CLK_DISABLE();
|
||||
|
||||
gpio_config.Pin = GPIO_PIN_4 | GPIO_PIN_3;
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
HAL_GPIO_Init(GPIOB, &gpio_config);
|
||||
__HAL_RCC_GPIOB_CLK_DISABLE();
|
||||
|
||||
HAL_DBGMCU_DisableDBGSleepMode();
|
||||
HAL_DBGMCU_DisableDBGStopMode();
|
||||
HAL_DBGMCU_DisableDBGStandbyMode();
|
||||
|
||||
#endif /* (CFG_DEBUGGER_SUPPORTED == 1) */
|
||||
|
||||
#if(CFG_DEBUG_TRACE != 0)
|
||||
DbgTraceInit();
|
||||
#endif
|
||||
|
||||
APPD_SetCPU2GpioConfig();
|
||||
APPD_BleDtbCfg();
|
||||
|
||||
/* USER CODE END APPD_Init */
|
||||
return;
|
||||
}
|
||||
|
||||
void APPD_EnableCPU2(void) {
|
||||
/* USER CODE BEGIN APPD_EnableCPU2 */
|
||||
SHCI_C2_DEBUG_Init_Cmd_Packet_t DebugCmdPacket = {
|
||||
{{0, 0, 0}}, /**< Does not need to be initialized */
|
||||
{(uint8_t*)aGpioConfigList,
|
||||
(uint8_t*)&APPD_TracesConfig,
|
||||
(uint8_t*)&APPD_GeneralConfig,
|
||||
GPIO_CFG_NBR_OF_FEATURES,
|
||||
NBR_OF_TRACES_CONFIG_PARAMETERS,
|
||||
NBR_OF_GENERAL_CONFIG_PARAMETERS}};
|
||||
|
||||
/**< Traces channel initialization */
|
||||
TL_TRACES_Init();
|
||||
|
||||
/** GPIO DEBUG Initialization */
|
||||
SHCI_C2_DEBUG_Init(&DebugCmdPacket);
|
||||
|
||||
// GPIO_InitTypeDef GPIO_InitStruct;
|
||||
// GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
// GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
// GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||||
// GPIO_InitStruct.Pin = LL_GPIO_PIN_3;
|
||||
// HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
|
||||
// SHCI_C2_ExtpaConfig((uint32_t)GPIOC, LL_GPIO_PIN_3, EXT_PA_ENABLED_LOW, EXT_PA_ENABLED);
|
||||
|
||||
/* USER CODE END APPD_EnableCPU2 */
|
||||
return;
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
*
|
||||
* LOCAL FUNCTIONS
|
||||
*
|
||||
*************************************************************/
|
||||
static void APPD_SetCPU2GpioConfig(void) {
|
||||
/* USER CODE BEGIN APPD_SetCPU2GpioConfig */
|
||||
GPIO_InitTypeDef gpio_config = {0};
|
||||
uint8_t local_loop;
|
||||
uint16_t gpioa_pin_list;
|
||||
uint16_t gpiob_pin_list;
|
||||
uint16_t gpioc_pin_list;
|
||||
|
||||
gpioa_pin_list = 0;
|
||||
gpiob_pin_list = 0;
|
||||
gpioc_pin_list = 0;
|
||||
|
||||
for(local_loop = 0; local_loop < GPIO_CFG_NBR_OF_FEATURES; local_loop++) {
|
||||
if(aGpioConfigList[local_loop].enable != 0) {
|
||||
switch((uint32_t)aGpioConfigList[local_loop].port) {
|
||||
case(uint32_t)GPIOA:
|
||||
gpioa_pin_list |= aGpioConfigList[local_loop].pin;
|
||||
break;
|
||||
|
||||
case(uint32_t)GPIOB:
|
||||
gpiob_pin_list |= aGpioConfigList[local_loop].pin;
|
||||
break;
|
||||
|
||||
case(uint32_t)GPIOC:
|
||||
gpioc_pin_list |= aGpioConfigList[local_loop].pin;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gpio_config.Pull = GPIO_NOPULL;
|
||||
gpio_config.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
gpio_config.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||||
|
||||
if(gpioa_pin_list != 0) {
|
||||
gpio_config.Pin = gpioa_pin_list;
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
__HAL_RCC_C2GPIOA_CLK_ENABLE();
|
||||
HAL_GPIO_Init(GPIOA, &gpio_config);
|
||||
HAL_GPIO_WritePin(GPIOA, gpioa_pin_list, GPIO_PIN_RESET);
|
||||
}
|
||||
|
||||
if(gpiob_pin_list != 0) {
|
||||
gpio_config.Pin = gpiob_pin_list;
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
__HAL_RCC_C2GPIOB_CLK_ENABLE();
|
||||
HAL_GPIO_Init(GPIOB, &gpio_config);
|
||||
HAL_GPIO_WritePin(GPIOB, gpiob_pin_list, GPIO_PIN_RESET);
|
||||
}
|
||||
|
||||
if(gpioc_pin_list != 0) {
|
||||
gpio_config.Pin = gpioc_pin_list;
|
||||
__HAL_RCC_GPIOC_CLK_ENABLE();
|
||||
__HAL_RCC_C2GPIOC_CLK_ENABLE();
|
||||
HAL_GPIO_Init(GPIOC, &gpio_config);
|
||||
HAL_GPIO_WritePin(GPIOC, gpioc_pin_list, GPIO_PIN_RESET);
|
||||
}
|
||||
|
||||
/* USER CODE END APPD_SetCPU2GpioConfig */
|
||||
return;
|
||||
}
|
||||
|
||||
static void APPD_BleDtbCfg(void) {
|
||||
/* USER CODE BEGIN APPD_BleDtbCfg */
|
||||
#if(BLE_DTB_CFG != 0)
|
||||
GPIO_InitTypeDef gpio_config = {0};
|
||||
uint8_t local_loop;
|
||||
uint16_t gpioa_pin_list;
|
||||
uint16_t gpiob_pin_list;
|
||||
|
||||
gpioa_pin_list = 0;
|
||||
gpiob_pin_list = 0;
|
||||
|
||||
for(local_loop = 0; local_loop < GPIO_NBR_OF_RF_SIGNALS; local_loop++) {
|
||||
if(aRfConfigList[local_loop].enable != 0) {
|
||||
switch((uint32_t)aRfConfigList[local_loop].port) {
|
||||
case(uint32_t)GPIOA:
|
||||
gpioa_pin_list |= aRfConfigList[local_loop].pin;
|
||||
break;
|
||||
|
||||
case(uint32_t)GPIOB:
|
||||
gpiob_pin_list |= aRfConfigList[local_loop].pin;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gpio_config.Pull = GPIO_NOPULL;
|
||||
gpio_config.Mode = GPIO_MODE_AF_PP;
|
||||
gpio_config.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
|
||||
gpio_config.Alternate = GPIO_AF6_RF_DTB7;
|
||||
|
||||
if(gpioa_pin_list != 0) {
|
||||
gpio_config.Pin = gpioa_pin_list;
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
__HAL_RCC_C2GPIOA_CLK_ENABLE();
|
||||
HAL_GPIO_Init(GPIOA, &gpio_config);
|
||||
}
|
||||
|
||||
if(gpiob_pin_list != 0) {
|
||||
gpio_config.Pin = gpiob_pin_list;
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
__HAL_RCC_C2GPIOB_CLK_ENABLE();
|
||||
HAL_GPIO_Init(GPIOB, &gpio_config);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* USER CODE END APPD_BleDtbCfg */
|
||||
return;
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
*
|
||||
* WRAP FUNCTIONS
|
||||
*
|
||||
*************************************************************/
|
||||
#if(CFG_DEBUG_TRACE != 0)
|
||||
void DbgOutputInit(void) {
|
||||
}
|
||||
|
||||
void DbgOutputTraces(uint8_t* p_data, uint16_t size, void (*cb)(void)) {
|
||||
furi_hal_console_tx(p_data, size);
|
||||
cb();
|
||||
}
|
||||
#endif
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
38
firmware/targets/f6/ble_glue/app_debug.h
Normal file
38
firmware/targets/f6/ble_glue/app_debug.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : app_debug.h
|
||||
* Description : Header for app_debug.c module
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2020 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 */
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __APP_DEBUG_H
|
||||
#define __APP_DEBUG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void APPD_Init(void);
|
||||
void APPD_EnableCPU2(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*__APP_DEBUG_H */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
81
firmware/targets/f6/ble_glue/battery_service.c
Normal file
81
firmware/targets/f6/ble_glue/battery_service.c
Normal file
@@ -0,0 +1,81 @@
|
||||
#include "battery_service.h"
|
||||
#include "app_common.h"
|
||||
#include "ble.h"
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
#define TAG "BtBatterySvc"
|
||||
|
||||
typedef struct {
|
||||
uint16_t svc_handle;
|
||||
uint16_t char_level_handle;
|
||||
} BatterySvc;
|
||||
|
||||
static BatterySvc* battery_svc = NULL;
|
||||
|
||||
static const uint16_t service_uuid = BATTERY_SERVICE_UUID;
|
||||
static const uint16_t char_battery_level_uuid = BATTERY_LEVEL_CHAR_UUID;
|
||||
|
||||
void battery_svc_start() {
|
||||
battery_svc = furi_alloc(sizeof(BatterySvc));
|
||||
tBleStatus status;
|
||||
|
||||
// Add Battery service
|
||||
status = aci_gatt_add_service(
|
||||
UUID_TYPE_16, (Service_UUID_t*)&service_uuid, PRIMARY_SERVICE, 4, &battery_svc->svc_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to add Battery service: %d", status);
|
||||
}
|
||||
// Add Battery level characteristic
|
||||
status = aci_gatt_add_char(
|
||||
battery_svc->svc_handle,
|
||||
UUID_TYPE_16,
|
||||
(Char_UUID_t*)&char_battery_level_uuid,
|
||||
1,
|
||||
CHAR_PROP_READ | CHAR_PROP_NOTIFY,
|
||||
ATTR_PERMISSION_AUTHEN_READ,
|
||||
GATT_DONT_NOTIFY_EVENTS,
|
||||
10,
|
||||
CHAR_VALUE_LEN_CONSTANT,
|
||||
&battery_svc->char_level_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to add Battery level characteristic: %d", status);
|
||||
}
|
||||
}
|
||||
|
||||
void battery_svc_stop() {
|
||||
tBleStatus status;
|
||||
if(battery_svc) {
|
||||
// Delete Battery level characteristic
|
||||
status = aci_gatt_del_char(battery_svc->svc_handle, battery_svc->char_level_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to delete Battery level characteristic: %d", status);
|
||||
}
|
||||
// Delete Battery service
|
||||
status = aci_gatt_del_service(battery_svc->svc_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to delete Battery service: %d", status);
|
||||
}
|
||||
free(battery_svc);
|
||||
battery_svc = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool battery_svc_is_started() {
|
||||
return battery_svc != NULL;
|
||||
}
|
||||
|
||||
bool battery_svc_update_level(uint8_t battery_charge) {
|
||||
// Check if service was started
|
||||
if(battery_svc == NULL) {
|
||||
return false;
|
||||
}
|
||||
// Update battery level characteristic
|
||||
FURI_LOG_I(TAG, "Updating battery level characteristic");
|
||||
tBleStatus result = aci_gatt_update_char_value(
|
||||
battery_svc->svc_handle, battery_svc->char_level_handle, 0, 1, &battery_charge);
|
||||
if(result) {
|
||||
FURI_LOG_E(TAG, "Failed updating RX characteristic: %d", result);
|
||||
}
|
||||
return result != BLE_STATUS_SUCCESS;
|
||||
}
|
||||
20
firmware/targets/f6/ble_glue/battery_service.h
Normal file
20
firmware/targets/f6/ble_glue/battery_service.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void battery_svc_start();
|
||||
|
||||
void battery_svc_stop();
|
||||
|
||||
bool battery_svc_is_started();
|
||||
|
||||
bool battery_svc_update_level(uint8_t battery_level);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
185
firmware/targets/f6/ble_glue/ble_app.c
Normal file
185
firmware/targets/f6/ble_glue/ble_app.c
Normal file
@@ -0,0 +1,185 @@
|
||||
#include "ble_app.h"
|
||||
|
||||
#include "hci_tl.h"
|
||||
#include "ble.h"
|
||||
#include "shci.h"
|
||||
#include "gap.h"
|
||||
|
||||
#include <furi_hal.h>
|
||||
|
||||
#define TAG "Bt"
|
||||
|
||||
#define BLE_APP_FLAG_HCI_EVENT (1UL << 0)
|
||||
#define BLE_APP_FLAG_KILL_THREAD (1UL << 1)
|
||||
#define BLE_APP_FLAG_ALL (BLE_APP_FLAG_HCI_EVENT | BLE_APP_FLAG_KILL_THREAD)
|
||||
|
||||
PLACE_IN_SECTION("MB_MEM1") ALIGN(4) static TL_CmdPacket_t ble_app_cmd_buffer;
|
||||
PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint32_t ble_app_nvm[BLE_NVM_SRAM_SIZE];
|
||||
|
||||
_Static_assert(
|
||||
sizeof(SHCI_C2_Ble_Init_Cmd_Packet_t) == 49,
|
||||
"Ble stack config structure size mismatch");
|
||||
|
||||
typedef struct {
|
||||
osMutexId_t hci_mtx;
|
||||
osSemaphoreId_t hci_sem;
|
||||
FuriThread* thread;
|
||||
osEventFlagsId_t event_flags;
|
||||
} BleApp;
|
||||
|
||||
static BleApp* ble_app = NULL;
|
||||
|
||||
static int32_t ble_app_hci_thread(void* context);
|
||||
static void ble_app_hci_event_handler(void* pPayload);
|
||||
static void ble_app_hci_status_not_handler(HCI_TL_CmdStatus_t status);
|
||||
|
||||
bool ble_app_init() {
|
||||
SHCI_CmdStatus_t status;
|
||||
ble_app = furi_alloc(sizeof(BleApp));
|
||||
// Allocate semafore and mutex for ble command buffer access
|
||||
ble_app->hci_mtx = osMutexNew(NULL);
|
||||
ble_app->hci_sem = osSemaphoreNew(1, 0, NULL);
|
||||
ble_app->event_flags = osEventFlagsNew(NULL);
|
||||
// HCI transport layer thread to handle user asynch events
|
||||
ble_app->thread = furi_thread_alloc();
|
||||
furi_thread_set_name(ble_app->thread, "BleHciWorker");
|
||||
furi_thread_set_stack_size(ble_app->thread, 1024);
|
||||
furi_thread_set_context(ble_app->thread, ble_app);
|
||||
furi_thread_set_callback(ble_app->thread, ble_app_hci_thread);
|
||||
furi_thread_start(ble_app->thread);
|
||||
|
||||
// Initialize Ble Transport Layer
|
||||
HCI_TL_HciInitConf_t hci_tl_config = {
|
||||
.p_cmdbuffer = (uint8_t*)&ble_app_cmd_buffer,
|
||||
.StatusNotCallBack = ble_app_hci_status_not_handler,
|
||||
};
|
||||
hci_init(ble_app_hci_event_handler, (void*)&hci_tl_config);
|
||||
|
||||
// Configure NVM store for pairing data
|
||||
SHCI_C2_CONFIG_Cmd_Param_t config_param = {
|
||||
.PayloadCmdSize = SHCI_C2_CONFIG_PAYLOAD_CMD_SIZE,
|
||||
.Config1 = SHCI_C2_CONFIG_CONFIG1_BIT0_BLE_NVM_DATA_TO_SRAM,
|
||||
.BleNvmRamAddress = (uint32_t)ble_app_nvm,
|
||||
.EvtMask1 = SHCI_C2_CONFIG_EVTMASK1_BIT1_BLE_NVM_RAM_UPDATE_ENABLE,
|
||||
};
|
||||
status = SHCI_C2_Config(&config_param);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to configure 2nd core: %d", status);
|
||||
}
|
||||
|
||||
// Start ble stack on 2nd core
|
||||
SHCI_C2_Ble_Init_Cmd_Packet_t ble_init_cmd_packet = {
|
||||
.Header = {{0, 0, 0}}, // Header unused
|
||||
.Param = {
|
||||
.pBleBufferAddress = 0, // pBleBufferAddress not used
|
||||
.BleBufferSize = 0, // BleBufferSize not used
|
||||
.NumAttrRecord = CFG_BLE_NUM_GATT_ATTRIBUTES,
|
||||
.NumAttrServ = CFG_BLE_NUM_GATT_SERVICES,
|
||||
.AttrValueArrSize = CFG_BLE_ATT_VALUE_ARRAY_SIZE,
|
||||
.NumOfLinks = CFG_BLE_NUM_LINK,
|
||||
.ExtendedPacketLengthEnable = CFG_BLE_DATA_LENGTH_EXTENSION,
|
||||
.PrWriteListSize = CFG_BLE_PREPARE_WRITE_LIST_SIZE,
|
||||
.MblockCount = CFG_BLE_MBLOCK_COUNT,
|
||||
.AttMtu = CFG_BLE_MAX_ATT_MTU,
|
||||
.SlaveSca = CFG_BLE_SLAVE_SCA,
|
||||
.MasterSca = CFG_BLE_MASTER_SCA,
|
||||
.LsSource = CFG_BLE_LSE_SOURCE,
|
||||
.MaxConnEventLength = CFG_BLE_MAX_CONN_EVENT_LENGTH,
|
||||
.HsStartupTime = CFG_BLE_HSE_STARTUP_TIME,
|
||||
.ViterbiEnable = CFG_BLE_VITERBI_MODE,
|
||||
.Options = CFG_BLE_OPTIONS,
|
||||
.HwVersion = 0,
|
||||
.max_coc_initiator_nbr = 32,
|
||||
.min_tx_power = 0,
|
||||
.max_tx_power = 0,
|
||||
.rx_model_config = 1,
|
||||
}};
|
||||
status = SHCI_C2_BLE_Init(&ble_init_cmd_packet);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to start ble stack: %d", status);
|
||||
}
|
||||
return status == SHCI_Success;
|
||||
}
|
||||
|
||||
void ble_app_get_key_storage_buff(uint8_t** addr, uint16_t* size) {
|
||||
*addr = (uint8_t*)ble_app_nvm;
|
||||
*size = sizeof(ble_app_nvm);
|
||||
}
|
||||
|
||||
void ble_app_thread_stop() {
|
||||
if(ble_app) {
|
||||
osEventFlagsSet(ble_app->event_flags, BLE_APP_FLAG_KILL_THREAD);
|
||||
furi_thread_join(ble_app->thread);
|
||||
furi_thread_free(ble_app->thread);
|
||||
// Wait to make sure that EventFlags delivers pending events before memory free
|
||||
osDelay(50);
|
||||
// Free resources
|
||||
osMutexDelete(ble_app->hci_mtx);
|
||||
osSemaphoreDelete(ble_app->hci_sem);
|
||||
osEventFlagsDelete(ble_app->event_flags);
|
||||
free(ble_app);
|
||||
ble_app = NULL;
|
||||
memset(&ble_app_cmd_buffer, 0, sizeof(ble_app_cmd_buffer));
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t ble_app_hci_thread(void* arg) {
|
||||
uint32_t flags = 0;
|
||||
while(1) {
|
||||
flags = osEventFlagsWait(
|
||||
ble_app->event_flags, BLE_APP_FLAG_ALL, osFlagsWaitAny, osWaitForever);
|
||||
if(flags & BLE_APP_FLAG_KILL_THREAD) {
|
||||
break;
|
||||
}
|
||||
if(flags & BLE_APP_FLAG_HCI_EVENT) {
|
||||
hci_user_evt_proc();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Called by WPAN lib
|
||||
void hci_notify_asynch_evt(void* pdata) {
|
||||
if(ble_app) {
|
||||
osEventFlagsSet(ble_app->event_flags, BLE_APP_FLAG_HCI_EVENT);
|
||||
}
|
||||
}
|
||||
|
||||
void hci_cmd_resp_release(uint32_t flag) {
|
||||
if(ble_app) {
|
||||
osSemaphoreRelease(ble_app->hci_sem);
|
||||
}
|
||||
}
|
||||
|
||||
void hci_cmd_resp_wait(uint32_t timeout) {
|
||||
if(ble_app) {
|
||||
osSemaphoreAcquire(ble_app->hci_sem, osWaitForever);
|
||||
}
|
||||
}
|
||||
|
||||
static void ble_app_hci_event_handler(void* pPayload) {
|
||||
SVCCTL_UserEvtFlowStatus_t svctl_return_status;
|
||||
tHCI_UserEvtRxParam* pParam = (tHCI_UserEvtRxParam*)pPayload;
|
||||
|
||||
if(ble_app) {
|
||||
svctl_return_status = SVCCTL_UserEvtRx((void*)&(pParam->pckt->evtserial));
|
||||
if(svctl_return_status != SVCCTL_UserEvtFlowDisable) {
|
||||
pParam->status = HCI_TL_UserEventFlow_Enable;
|
||||
} else {
|
||||
pParam->status = HCI_TL_UserEventFlow_Disable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ble_app_hci_status_not_handler(HCI_TL_CmdStatus_t status) {
|
||||
if(status == HCI_TL_CmdBusy) {
|
||||
osMutexAcquire(ble_app->hci_mtx, osWaitForever);
|
||||
} else if(status == HCI_TL_CmdAvailable) {
|
||||
osMutexRelease(ble_app->hci_mtx);
|
||||
}
|
||||
}
|
||||
|
||||
void SVCCTL_ResumeUserEventFlow(void) {
|
||||
hci_resume_flow();
|
||||
}
|
||||
16
firmware/targets/f6/ble_glue/ble_app.h
Normal file
16
firmware/targets/f6/ble_glue/ble_app.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
bool ble_app_init();
|
||||
void ble_app_get_key_storage_buff(uint8_t** addr, uint16_t* size);
|
||||
void ble_app_thread_stop();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
69
firmware/targets/f6/ble_glue/ble_conf.h
Normal file
69
firmware/targets/f6/ble_glue/ble_conf.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : App/ble_conf.h
|
||||
* Description : Configuration file for BLE Middleware.
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2020 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
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef BLE_CONF_H
|
||||
#define BLE_CONF_H
|
||||
|
||||
#include "app_conf.h"
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* BLE SERVICES CONFIGURATION
|
||||
* blesvc
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* This setting shall be set to '1' if the device needs to support the Peripheral Role
|
||||
* In the MS configuration, both BLE_CFG_PERIPHERAL and BLE_CFG_CENTRAL shall be set to '1'
|
||||
*/
|
||||
#define BLE_CFG_PERIPHERAL 1
|
||||
|
||||
/**
|
||||
* This setting shall be set to '1' if the device needs to support the Central Role
|
||||
* In the MS configuration, both BLE_CFG_PERIPHERAL and BLE_CFG_CENTRAL shall be set to '1'
|
||||
*/
|
||||
#define BLE_CFG_CENTRAL 0
|
||||
|
||||
/**
|
||||
* There is one handler per service enabled
|
||||
* Note: There is no handler for the Device Information Service
|
||||
*
|
||||
* This shall take into account all registered handlers
|
||||
* (from either the provided services or the custom services)
|
||||
*/
|
||||
#define BLE_CFG_SVC_MAX_NBR_CB 7
|
||||
|
||||
#define BLE_CFG_CLT_MAX_NBR_CB 0
|
||||
|
||||
/******************************************************************************
|
||||
* GAP Service - Apprearance
|
||||
******************************************************************************/
|
||||
|
||||
#define BLE_CFG_UNKNOWN_APPEARANCE (0)
|
||||
#define BLE_CFG_GAP_APPEARANCE (0x0086)
|
||||
|
||||
/******************************************************************************
|
||||
* Over The Air Feature (OTA) - STM Proprietary
|
||||
******************************************************************************/
|
||||
#define BLE_CFG_OTA_REBOOT_CHAR 0 /**< REBOOT OTA MODE CHARACTERISTIC */
|
||||
|
||||
#endif /*BLE_CONF_H */
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
199
firmware/targets/f6/ble_glue/ble_dbg_conf.h
Normal file
199
firmware/targets/f6/ble_glue/ble_dbg_conf.h
Normal file
@@ -0,0 +1,199 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : App/ble_dbg_conf.h
|
||||
* Description : Debug configuration file for BLE Middleware.
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2020 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
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __BLE_DBG_CONF_H
|
||||
#define __BLE_DBG_CONF_H
|
||||
|
||||
/**
|
||||
* Enable or Disable traces from BLE
|
||||
*/
|
||||
|
||||
#define BLE_DBG_APP_EN 1
|
||||
#define BLE_DBG_DIS_EN 1
|
||||
#define BLE_DBG_HRS_EN 1
|
||||
#define BLE_DBG_SVCCTL_EN 1
|
||||
#define BLE_DBG_BLS_EN 1
|
||||
#define BLE_DBG_HTS_EN 1
|
||||
#define BLE_DBG_P2P_STM_EN 1
|
||||
|
||||
/**
|
||||
* Macro definition
|
||||
*/
|
||||
#if(BLE_DBG_APP_EN != 0)
|
||||
#define BLE_DBG_APP_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_APP_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_DIS_EN != 0)
|
||||
#define BLE_DBG_DIS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_DIS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_HRS_EN != 0)
|
||||
#define BLE_DBG_HRS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_HRS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_P2P_STM_EN != 0)
|
||||
#define BLE_DBG_P2P_STM_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_P2P_STM_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_TEMPLATE_STM_EN != 0)
|
||||
#define BLE_DBG_TEMPLATE_STM_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_TEMPLATE_STM_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_EDS_STM_EN != 0)
|
||||
#define BLE_DBG_EDS_STM_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_EDS_STM_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_LBS_STM_EN != 0)
|
||||
#define BLE_DBG_LBS_STM_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_LBS_STM_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_SVCCTL_EN != 0)
|
||||
#define BLE_DBG_SVCCTL_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_SVCCTL_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_CTS_EN != 0)
|
||||
#define BLE_DBG_CTS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_CTS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_HIDS_EN != 0)
|
||||
#define BLE_DBG_HIDS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_HIDS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_PASS_EN != 0)
|
||||
#define BLE_DBG_PASS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_PASS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_BLS_EN != 0)
|
||||
#define BLE_DBG_BLS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_BLS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_HTS_EN != 0)
|
||||
#define BLE_DBG_HTS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_HTS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_ANS_EN != 0)
|
||||
#define BLE_DBG_ANS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_ANS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_ESS_EN != 0)
|
||||
#define BLE_DBG_ESS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_ESS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_GLS_EN != 0)
|
||||
#define BLE_DBG_GLS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_GLS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_BAS_EN != 0)
|
||||
#define BLE_DBG_BAS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_BAS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_RTUS_EN != 0)
|
||||
#define BLE_DBG_RTUS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_RTUS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_HPS_EN != 0)
|
||||
#define BLE_DBG_HPS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_HPS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_TPS_EN != 0)
|
||||
#define BLE_DBG_TPS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_TPS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_LLS_EN != 0)
|
||||
#define BLE_DBG_LLS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_LLS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_IAS_EN != 0)
|
||||
#define BLE_DBG_IAS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_IAS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_WSS_EN != 0)
|
||||
#define BLE_DBG_WSS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_WSS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_LNS_EN != 0)
|
||||
#define BLE_DBG_LNS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_LNS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_SCPS_EN != 0)
|
||||
#define BLE_DBG_SCPS_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define BLE_DBG_SCPS_MSG PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#if(BLE_DBG_DTS_EN != 0)
|
||||
#define BLE_DBG_DTS_MSG PRINT_MESG_DBG
|
||||
#define BLE_DBG_DTS_BUF PRINT_LOG_BUFF_DBG
|
||||
#else
|
||||
#define BLE_DBG_DTS_MSG PRINT_NO_MESG
|
||||
#define BLE_DBG_DTS_BUF PRINT_NO_MESG
|
||||
#endif
|
||||
|
||||
#endif /*__BLE_DBG_CONF_H */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
291
firmware/targets/f6/ble_glue/ble_glue.c
Normal file
291
firmware/targets/f6/ble_glue/ble_glue.c
Normal file
@@ -0,0 +1,291 @@
|
||||
#include "ble_glue.h"
|
||||
#include "app_common.h"
|
||||
#include "main.h"
|
||||
#include "ble_app.h"
|
||||
#include "ble.h"
|
||||
#include "tl.h"
|
||||
#include "shci.h"
|
||||
#include "shci_tl.h"
|
||||
#include "app_debug.h"
|
||||
#include <furi_hal.h>
|
||||
|
||||
#define TAG "Core2"
|
||||
|
||||
#define BLE_GLUE_FLAG_SHCI_EVENT (1UL << 0)
|
||||
#define BLE_GLUE_FLAG_KILL_THREAD (1UL << 1)
|
||||
#define BLE_GLUE_FLAG_ALL (BLE_GLUE_FLAG_SHCI_EVENT | BLE_GLUE_FLAG_KILL_THREAD)
|
||||
|
||||
#define POOL_SIZE \
|
||||
(CFG_TLBLE_EVT_QUEUE_LENGTH * 4U * \
|
||||
DIVC((sizeof(TL_PacketHeader_t) + TL_BLE_EVENT_FRAME_SIZE), 4U))
|
||||
|
||||
PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t ble_glue_event_pool[POOL_SIZE];
|
||||
PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static TL_CmdPacket_t ble_glue_system_cmd_buff;
|
||||
PLACE_IN_SECTION("MB_MEM2")
|
||||
ALIGN(4)
|
||||
static uint8_t ble_glue_system_spare_event_buff[sizeof(TL_PacketHeader_t) + TL_EVT_HDR_SIZE + 255U];
|
||||
PLACE_IN_SECTION("MB_MEM2")
|
||||
ALIGN(4)
|
||||
static uint8_t ble_glue_ble_spare_event_buff[sizeof(TL_PacketHeader_t) + TL_EVT_HDR_SIZE + 255];
|
||||
|
||||
typedef enum {
|
||||
// Stage 1: core2 startup and FUS
|
||||
BleGlueStatusStartup,
|
||||
BleGlueStatusBroken,
|
||||
BleGlueStatusFusStarted,
|
||||
// Stage 2: radio stack
|
||||
BleGlueStatusRadioStackStarted,
|
||||
BleGlueStatusRadioStackMissing
|
||||
} BleGlueStatus;
|
||||
|
||||
typedef struct {
|
||||
osMutexId_t shci_mtx;
|
||||
osSemaphoreId_t shci_sem;
|
||||
osEventFlagsId_t event_flags;
|
||||
FuriThread* thread;
|
||||
BleGlueStatus status;
|
||||
BleGlueKeyStorageChangedCallback callback;
|
||||
void* context;
|
||||
} BleGlue;
|
||||
|
||||
static BleGlue* ble_glue = NULL;
|
||||
|
||||
static int32_t ble_glue_shci_thread(void* argument);
|
||||
static void ble_glue_sys_status_not_callback(SHCI_TL_CmdStatus_t status);
|
||||
static void ble_glue_sys_user_event_callback(void* pPayload);
|
||||
|
||||
void ble_glue_set_key_storage_changed_callback(
|
||||
BleGlueKeyStorageChangedCallback callback,
|
||||
void* context) {
|
||||
furi_assert(ble_glue);
|
||||
furi_assert(callback);
|
||||
ble_glue->callback = callback;
|
||||
ble_glue->context = context;
|
||||
}
|
||||
|
||||
void ble_glue_init() {
|
||||
ble_glue = furi_alloc(sizeof(BleGlue));
|
||||
ble_glue->status = BleGlueStatusStartup;
|
||||
|
||||
// Configure the system Power Mode
|
||||
// Select HSI as system clock source after Wake Up from Stop mode
|
||||
LL_RCC_SetClkAfterWakeFromStop(LL_RCC_STOP_WAKEUPCLOCK_HSI);
|
||||
/* Initialize the CPU2 reset value before starting CPU2 with C2BOOT */
|
||||
LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN);
|
||||
furi_hal_power_insomnia_enter();
|
||||
|
||||
// APPD_Init();
|
||||
|
||||
// Initialize all transport layers
|
||||
TL_MM_Config_t tl_mm_config;
|
||||
SHCI_TL_HciInitConf_t SHci_Tl_Init_Conf;
|
||||
// Reference table initialization
|
||||
TL_Init();
|
||||
|
||||
ble_glue->shci_mtx = osMutexNew(NULL);
|
||||
ble_glue->shci_sem = osSemaphoreNew(1, 0, NULL);
|
||||
ble_glue->event_flags = osEventFlagsNew(NULL);
|
||||
|
||||
// FreeRTOS system task creation
|
||||
ble_glue->thread = furi_thread_alloc();
|
||||
furi_thread_set_name(ble_glue->thread, "BleShciWorker");
|
||||
furi_thread_set_stack_size(ble_glue->thread, 1024);
|
||||
furi_thread_set_context(ble_glue->thread, ble_glue);
|
||||
furi_thread_set_callback(ble_glue->thread, ble_glue_shci_thread);
|
||||
furi_thread_start(ble_glue->thread);
|
||||
|
||||
// System channel initialization
|
||||
SHci_Tl_Init_Conf.p_cmdbuffer = (uint8_t*)&ble_glue_system_cmd_buff;
|
||||
SHci_Tl_Init_Conf.StatusNotCallBack = ble_glue_sys_status_not_callback;
|
||||
shci_init(ble_glue_sys_user_event_callback, (void*)&SHci_Tl_Init_Conf);
|
||||
|
||||
/**< Memory Manager channel initialization */
|
||||
tl_mm_config.p_BleSpareEvtBuffer = ble_glue_ble_spare_event_buff;
|
||||
tl_mm_config.p_SystemSpareEvtBuffer = ble_glue_system_spare_event_buff;
|
||||
tl_mm_config.p_AsynchEvtPool = ble_glue_event_pool;
|
||||
tl_mm_config.AsynchEvtPoolSize = POOL_SIZE;
|
||||
TL_MM_Init(&tl_mm_config);
|
||||
TL_Enable();
|
||||
|
||||
/*
|
||||
* From now, the application is waiting for the ready event ( VS_HCI_C2_Ready )
|
||||
* received on the system channel before starting the Stack
|
||||
* This system event is received with ble_glue_sys_user_event_callback()
|
||||
*/
|
||||
}
|
||||
|
||||
bool ble_glue_wait_for_fus_start(WirelessFwInfo_t* info) {
|
||||
bool ret = false;
|
||||
size_t countdown = 1000;
|
||||
while(countdown > 0) {
|
||||
if(ble_glue->status == BleGlueStatusFusStarted) {
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
countdown--;
|
||||
osDelay(1);
|
||||
}
|
||||
if(ble_glue->status == BleGlueStatusFusStarted) {
|
||||
SHCI_GetWirelessFwInfo(info);
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Failed to start FUS");
|
||||
ble_glue->status = BleGlueStatusBroken;
|
||||
}
|
||||
furi_hal_power_insomnia_exit();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ble_glue_start() {
|
||||
furi_assert(ble_glue);
|
||||
|
||||
if(ble_glue->status != BleGlueStatusFusStarted) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ret = false;
|
||||
furi_hal_power_insomnia_enter();
|
||||
if(ble_app_init()) {
|
||||
FURI_LOG_I(TAG, "Radio stack started");
|
||||
ble_glue->status = BleGlueStatusRadioStackStarted;
|
||||
ret = true;
|
||||
if(SHCI_C2_SetFlashActivityControl(FLASH_ACTIVITY_CONTROL_SEM7) == SHCI_Success) {
|
||||
FURI_LOG_I(TAG, "Flash activity control switched to SEM7");
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Failed to switch flash activity control to SEM7");
|
||||
}
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Radio stack startup failed");
|
||||
ble_glue->status = BleGlueStatusRadioStackMissing;
|
||||
ble_app_thread_stop();
|
||||
}
|
||||
furi_hal_power_insomnia_exit();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ble_glue_is_alive() {
|
||||
if(!ble_glue) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ble_glue->status >= BleGlueStatusFusStarted;
|
||||
}
|
||||
|
||||
bool ble_glue_is_radio_stack_ready() {
|
||||
if(!ble_glue) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ble_glue->status == BleGlueStatusRadioStackStarted;
|
||||
}
|
||||
|
||||
static void ble_glue_sys_status_not_callback(SHCI_TL_CmdStatus_t status) {
|
||||
switch(status) {
|
||||
case SHCI_TL_CmdBusy:
|
||||
osMutexAcquire(ble_glue->shci_mtx, osWaitForever);
|
||||
break;
|
||||
case SHCI_TL_CmdAvailable:
|
||||
osMutexRelease(ble_glue->shci_mtx);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The type of the payload for a system user event is tSHCI_UserEvtRxParam
|
||||
* When the system event is both :
|
||||
* - a ready event (subevtcode = SHCI_SUB_EVT_CODE_READY)
|
||||
* - reported by the FUS (sysevt_ready_rsp == FUS_FW_RUNNING)
|
||||
* The buffer shall not be released
|
||||
* ( eg ((tSHCI_UserEvtRxParam*)pPayload)->status shall be set to SHCI_TL_UserEventFlow_Disable )
|
||||
* When the status is not filled, the buffer is released by default
|
||||
*/
|
||||
static void ble_glue_sys_user_event_callback(void* pPayload) {
|
||||
UNUSED(pPayload);
|
||||
/* Traces channel initialization */
|
||||
// APPD_EnableCPU2( );
|
||||
|
||||
TL_AsynchEvt_t* p_sys_event =
|
||||
(TL_AsynchEvt_t*)(((tSHCI_UserEvtRxParam*)pPayload)->pckt->evtserial.evt.payload);
|
||||
|
||||
if(p_sys_event->subevtcode == SHCI_SUB_EVT_CODE_READY) {
|
||||
FURI_LOG_I(TAG, "Fus started");
|
||||
ble_glue->status = BleGlueStatusFusStarted;
|
||||
furi_hal_power_insomnia_exit();
|
||||
} else if(p_sys_event->subevtcode == SHCI_SUB_EVT_ERROR_NOTIF) {
|
||||
FURI_LOG_E(TAG, "Error during initialization");
|
||||
furi_hal_power_insomnia_exit();
|
||||
} else if(p_sys_event->subevtcode == SHCI_SUB_EVT_BLE_NVM_RAM_UPDATE) {
|
||||
SHCI_C2_BleNvmRamUpdate_Evt_t* p_sys_ble_nvm_ram_update_event =
|
||||
(SHCI_C2_BleNvmRamUpdate_Evt_t*)p_sys_event->payload;
|
||||
if(ble_glue->callback) {
|
||||
ble_glue->callback(
|
||||
(uint8_t*)p_sys_ble_nvm_ram_update_event->StartAddress,
|
||||
p_sys_ble_nvm_ram_update_event->Size,
|
||||
ble_glue->context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ble_glue_clear_shared_memory() {
|
||||
memset(ble_glue_event_pool, 0, sizeof(ble_glue_event_pool));
|
||||
memset(&ble_glue_system_cmd_buff, 0, sizeof(ble_glue_system_cmd_buff));
|
||||
memset(ble_glue_system_spare_event_buff, 0, sizeof(ble_glue_system_spare_event_buff));
|
||||
memset(ble_glue_ble_spare_event_buff, 0, sizeof(ble_glue_ble_spare_event_buff));
|
||||
}
|
||||
|
||||
void ble_glue_thread_stop() {
|
||||
if(ble_glue) {
|
||||
osEventFlagsSet(ble_glue->event_flags, BLE_GLUE_FLAG_KILL_THREAD);
|
||||
furi_thread_join(ble_glue->thread);
|
||||
furi_thread_free(ble_glue->thread);
|
||||
// Wait to make sure that EventFlags delivers pending events before memory free
|
||||
osDelay(50);
|
||||
// Free resources
|
||||
osMutexDelete(ble_glue->shci_mtx);
|
||||
osSemaphoreDelete(ble_glue->shci_sem);
|
||||
osEventFlagsDelete(ble_glue->event_flags);
|
||||
ble_glue_clear_shared_memory();
|
||||
free(ble_glue);
|
||||
ble_glue = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Wrap functions
|
||||
static int32_t ble_glue_shci_thread(void* context) {
|
||||
uint32_t flags = 0;
|
||||
while(true) {
|
||||
flags = osEventFlagsWait(
|
||||
ble_glue->event_flags, BLE_GLUE_FLAG_ALL, osFlagsWaitAny, osWaitForever);
|
||||
if(flags & BLE_GLUE_FLAG_SHCI_EVENT) {
|
||||
shci_user_evt_proc();
|
||||
}
|
||||
if(flags & BLE_GLUE_FLAG_KILL_THREAD) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void shci_notify_asynch_evt(void* pdata) {
|
||||
UNUSED(pdata);
|
||||
if(ble_glue) {
|
||||
osEventFlagsSet(ble_glue->event_flags, BLE_GLUE_FLAG_SHCI_EVENT);
|
||||
}
|
||||
}
|
||||
|
||||
void shci_cmd_resp_release(uint32_t flag) {
|
||||
UNUSED(flag);
|
||||
if(ble_glue) {
|
||||
osSemaphoreRelease(ble_glue->shci_sem);
|
||||
}
|
||||
}
|
||||
|
||||
void shci_cmd_resp_wait(uint32_t timeout) {
|
||||
UNUSED(timeout);
|
||||
if(ble_glue) {
|
||||
osSemaphoreAcquire(ble_glue->shci_sem, osWaitForever);
|
||||
}
|
||||
}
|
||||
50
firmware/targets/f6/ble_glue/ble_glue.h
Normal file
50
firmware/targets/f6/ble_glue/ble_glue.h
Normal file
@@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <shci/shci.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (
|
||||
*BleGlueKeyStorageChangedCallback)(uint8_t* change_addr_start, uint16_t size, void* context);
|
||||
|
||||
/** Initialize start core2 and initialize transport */
|
||||
void ble_glue_init();
|
||||
|
||||
/** Start Core2 Radio stack
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
bool ble_glue_start();
|
||||
|
||||
/** Is core2 alive and at least FUS is running
|
||||
*
|
||||
* @return true if core2 is alive
|
||||
*/
|
||||
bool ble_glue_is_alive();
|
||||
|
||||
bool ble_glue_wait_for_fus_start(WirelessFwInfo_t* info);
|
||||
|
||||
/** Is core2 radio stack present and ready
|
||||
*
|
||||
* @return true if present and ready
|
||||
*/
|
||||
bool ble_glue_is_radio_stack_ready();
|
||||
|
||||
/** Set callback for NVM in RAM changes
|
||||
*
|
||||
* @param[in] callback The callback to call on NVM change
|
||||
* @param context The context for callback
|
||||
*/
|
||||
void ble_glue_set_key_storage_changed_callback(
|
||||
BleGlueKeyStorageChangedCallback callback,
|
||||
void* context);
|
||||
|
||||
void ble_glue_thread_stop();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
174
firmware/targets/f6/ble_glue/dev_info_service.c
Normal file
174
firmware/targets/f6/ble_glue/dev_info_service.c
Normal file
@@ -0,0 +1,174 @@
|
||||
#include "dev_info_service.h"
|
||||
#include "app_common.h"
|
||||
#include "ble.h"
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
#define TAG "BtDevInfoSvc"
|
||||
|
||||
typedef struct {
|
||||
uint16_t service_handle;
|
||||
uint16_t man_name_char_handle;
|
||||
uint16_t serial_num_char_handle;
|
||||
uint16_t firmware_rev_char_handle;
|
||||
uint16_t software_rev_char_handle;
|
||||
} DevInfoSvc;
|
||||
|
||||
static DevInfoSvc* dev_info_svc = NULL;
|
||||
|
||||
static const char dev_info_man_name[] = "Flipper Devices Inc.";
|
||||
static const char dev_info_serial_num[] = "1.0";
|
||||
static const char dev_info_firmware_rev_num[] = TOSTRING(TARGET);
|
||||
static const char dev_info_software_rev_num[] = GIT_COMMIT " " GIT_BRANCH " " GIT_BRANCH_NUM
|
||||
" " BUILD_DATE;
|
||||
|
||||
void dev_info_svc_start() {
|
||||
dev_info_svc = furi_alloc(sizeof(DevInfoSvc));
|
||||
tBleStatus status;
|
||||
|
||||
// Add Device Information Service
|
||||
uint16_t uuid = DEVICE_INFORMATION_SERVICE_UUID;
|
||||
status = aci_gatt_add_service(
|
||||
UUID_TYPE_16, (Service_UUID_t*)&uuid, PRIMARY_SERVICE, 9, &dev_info_svc->service_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to add Device Information Service: %d", status);
|
||||
}
|
||||
|
||||
// Add characteristics
|
||||
uuid = MANUFACTURER_NAME_UUID;
|
||||
status = aci_gatt_add_char(
|
||||
dev_info_svc->service_handle,
|
||||
UUID_TYPE_16,
|
||||
(Char_UUID_t*)&uuid,
|
||||
strlen(dev_info_man_name),
|
||||
CHAR_PROP_READ,
|
||||
ATTR_PERMISSION_AUTHEN_READ,
|
||||
GATT_DONT_NOTIFY_EVENTS,
|
||||
10,
|
||||
CHAR_VALUE_LEN_CONSTANT,
|
||||
&dev_info_svc->man_name_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to add manufacturer name char: %d", status);
|
||||
}
|
||||
uuid = SERIAL_NUMBER_UUID;
|
||||
status = aci_gatt_add_char(
|
||||
dev_info_svc->service_handle,
|
||||
UUID_TYPE_16,
|
||||
(Char_UUID_t*)&uuid,
|
||||
strlen(dev_info_serial_num),
|
||||
CHAR_PROP_READ,
|
||||
ATTR_PERMISSION_AUTHEN_READ,
|
||||
GATT_DONT_NOTIFY_EVENTS,
|
||||
10,
|
||||
CHAR_VALUE_LEN_CONSTANT,
|
||||
&dev_info_svc->serial_num_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to add serial number char: %d", status);
|
||||
}
|
||||
uuid = FIRMWARE_REVISION_UUID;
|
||||
status = aci_gatt_add_char(
|
||||
dev_info_svc->service_handle,
|
||||
UUID_TYPE_16,
|
||||
(Char_UUID_t*)&uuid,
|
||||
strlen(dev_info_firmware_rev_num),
|
||||
CHAR_PROP_READ,
|
||||
ATTR_PERMISSION_AUTHEN_READ,
|
||||
GATT_DONT_NOTIFY_EVENTS,
|
||||
10,
|
||||
CHAR_VALUE_LEN_CONSTANT,
|
||||
&dev_info_svc->firmware_rev_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to add firmware revision char: %d", status);
|
||||
}
|
||||
uuid = SOFTWARE_REVISION_UUID;
|
||||
status = aci_gatt_add_char(
|
||||
dev_info_svc->service_handle,
|
||||
UUID_TYPE_16,
|
||||
(Char_UUID_t*)&uuid,
|
||||
strlen(dev_info_software_rev_num),
|
||||
CHAR_PROP_READ,
|
||||
ATTR_PERMISSION_AUTHEN_READ,
|
||||
GATT_DONT_NOTIFY_EVENTS,
|
||||
10,
|
||||
CHAR_VALUE_LEN_CONSTANT,
|
||||
&dev_info_svc->software_rev_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to add software revision char: %d", status);
|
||||
}
|
||||
|
||||
// Update characteristics
|
||||
status = aci_gatt_update_char_value(
|
||||
dev_info_svc->service_handle,
|
||||
dev_info_svc->man_name_char_handle,
|
||||
0,
|
||||
strlen(dev_info_man_name),
|
||||
(uint8_t*)dev_info_man_name);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to update manufacturer name char: %d", status);
|
||||
}
|
||||
status = aci_gatt_update_char_value(
|
||||
dev_info_svc->service_handle,
|
||||
dev_info_svc->serial_num_char_handle,
|
||||
0,
|
||||
strlen(dev_info_serial_num),
|
||||
(uint8_t*)dev_info_serial_num);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to update serial number char: %d", status);
|
||||
}
|
||||
status = aci_gatt_update_char_value(
|
||||
dev_info_svc->service_handle,
|
||||
dev_info_svc->firmware_rev_char_handle,
|
||||
0,
|
||||
strlen(dev_info_firmware_rev_num),
|
||||
(uint8_t*)dev_info_firmware_rev_num);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to update firmware revision char: %d", status);
|
||||
}
|
||||
status = aci_gatt_update_char_value(
|
||||
dev_info_svc->service_handle,
|
||||
dev_info_svc->software_rev_char_handle,
|
||||
0,
|
||||
strlen(dev_info_software_rev_num),
|
||||
(uint8_t*)dev_info_software_rev_num);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to update software revision char: %d", status);
|
||||
}
|
||||
}
|
||||
|
||||
void dev_info_svc_stop() {
|
||||
tBleStatus status;
|
||||
if(dev_info_svc) {
|
||||
// Delete service characteristics
|
||||
status =
|
||||
aci_gatt_del_char(dev_info_svc->service_handle, dev_info_svc->man_name_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to delete manufacturer name char: %d", status);
|
||||
}
|
||||
status =
|
||||
aci_gatt_del_char(dev_info_svc->service_handle, dev_info_svc->serial_num_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to delete serial number char: %d", status);
|
||||
}
|
||||
status = aci_gatt_del_char(
|
||||
dev_info_svc->service_handle, dev_info_svc->firmware_rev_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to delete firmware revision char: %d", status);
|
||||
}
|
||||
status = aci_gatt_del_char(
|
||||
dev_info_svc->service_handle, dev_info_svc->software_rev_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to delete software revision char: %d", status);
|
||||
}
|
||||
// Delete service
|
||||
status = aci_gatt_del_service(dev_info_svc->service_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to delete device info service: %d", status);
|
||||
}
|
||||
free(dev_info_svc);
|
||||
dev_info_svc = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool dev_info_svc_is_started() {
|
||||
return dev_info_svc != NULL;
|
||||
}
|
||||
24
firmware/targets/f6/ble_glue/dev_info_service.h
Normal file
24
firmware/targets/f6/ble_glue/dev_info_service.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define DEV_INFO_MANUFACTURER_NAME "Flipper Devices Inc."
|
||||
#define DEV_INFO_SERIAL_NUMBER "1.0"
|
||||
#define DEV_INFO_FIRMWARE_REVISION_NUMBER TARGET
|
||||
#define DEV_INFO_SOFTWARE_REVISION_NUMBER \
|
||||
GIT_COMMIT " " GIT_BRANCH " " GIT_BRANCH_NUM " " BUILD_DATE
|
||||
|
||||
void dev_info_svc_start();
|
||||
|
||||
void dev_info_svc_stop();
|
||||
|
||||
bool dev_info_svc_is_started();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
549
firmware/targets/f6/ble_glue/gap.c
Normal file
549
firmware/targets/f6/ble_glue/gap.c
Normal file
@@ -0,0 +1,549 @@
|
||||
#include "gap.h"
|
||||
|
||||
#include "ble.h"
|
||||
|
||||
#include <furi_hal.h>
|
||||
#include <furi.h>
|
||||
|
||||
#define TAG "BtGap"
|
||||
|
||||
#define FAST_ADV_TIMEOUT 30000
|
||||
#define INITIAL_ADV_TIMEOUT 60000
|
||||
|
||||
typedef struct {
|
||||
uint16_t gap_svc_handle;
|
||||
uint16_t dev_name_char_handle;
|
||||
uint16_t appearance_char_handle;
|
||||
uint16_t connection_handle;
|
||||
uint8_t adv_svc_uuid_len;
|
||||
uint8_t adv_svc_uuid[20];
|
||||
char* adv_name;
|
||||
} GapSvc;
|
||||
|
||||
typedef struct {
|
||||
GapSvc service;
|
||||
GapConfig* config;
|
||||
GapState state;
|
||||
osMutexId_t state_mutex;
|
||||
GapEventCallback on_event_cb;
|
||||
void* context;
|
||||
osTimerId_t advertise_timer;
|
||||
FuriThread* thread;
|
||||
osMessageQueueId_t command_queue;
|
||||
bool enable_adv;
|
||||
} Gap;
|
||||
|
||||
typedef enum {
|
||||
GapCommandAdvFast,
|
||||
GapCommandAdvLowPower,
|
||||
GapCommandAdvStop,
|
||||
GapCommandKillThread,
|
||||
} GapCommand;
|
||||
|
||||
typedef struct {
|
||||
GapScanCallback callback;
|
||||
void* context;
|
||||
} GapScan;
|
||||
|
||||
// Identity root key
|
||||
static const uint8_t gap_irk[16] =
|
||||
{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0};
|
||||
// Encryption root key
|
||||
static const uint8_t gap_erk[16] =
|
||||
{0xfe, 0xdc, 0xba, 0x09, 0x87, 0x65, 0x43, 0x21, 0xfe, 0xdc, 0xba, 0x09, 0x87, 0x65, 0x43, 0x21};
|
||||
|
||||
static Gap* gap = NULL;
|
||||
static GapScan* gap_scan = NULL;
|
||||
|
||||
static void gap_advertise_start(GapState new_state);
|
||||
static int32_t gap_app(void* context);
|
||||
|
||||
SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) {
|
||||
hci_event_pckt* event_pckt;
|
||||
evt_le_meta_event* meta_evt;
|
||||
evt_blue_aci* blue_evt;
|
||||
hci_le_phy_update_complete_event_rp0* evt_le_phy_update_complete;
|
||||
uint8_t tx_phy;
|
||||
uint8_t rx_phy;
|
||||
tBleStatus ret = BLE_STATUS_INVALID_PARAMS;
|
||||
|
||||
event_pckt = (hci_event_pckt*)((hci_uart_pckt*)pckt)->data;
|
||||
|
||||
if(gap) {
|
||||
osMutexAcquire(gap->state_mutex, osWaitForever);
|
||||
}
|
||||
switch(event_pckt->evt) {
|
||||
case EVT_DISCONN_COMPLETE: {
|
||||
hci_disconnection_complete_event_rp0* disconnection_complete_event =
|
||||
(hci_disconnection_complete_event_rp0*)event_pckt->data;
|
||||
if(disconnection_complete_event->Connection_Handle == gap->service.connection_handle) {
|
||||
gap->service.connection_handle = 0;
|
||||
gap->state = GapStateIdle;
|
||||
FURI_LOG_I(
|
||||
TAG, "Disconnect from client. Reason: %02X", disconnection_complete_event->Reason);
|
||||
}
|
||||
if(gap->enable_adv) {
|
||||
// Restart advertising
|
||||
gap_advertise_start(GapStateAdvFast);
|
||||
furi_hal_power_insomnia_exit();
|
||||
}
|
||||
GapEvent event = {.type = GapEventTypeDisconnected};
|
||||
gap->on_event_cb(event, gap->context);
|
||||
} break;
|
||||
|
||||
case EVT_LE_META_EVENT:
|
||||
meta_evt = (evt_le_meta_event*)event_pckt->data;
|
||||
switch(meta_evt->subevent) {
|
||||
case EVT_LE_CONN_UPDATE_COMPLETE:
|
||||
FURI_LOG_D(TAG, "Connection update event");
|
||||
break;
|
||||
|
||||
case EVT_LE_PHY_UPDATE_COMPLETE:
|
||||
evt_le_phy_update_complete = (hci_le_phy_update_complete_event_rp0*)meta_evt->data;
|
||||
if(evt_le_phy_update_complete->Status) {
|
||||
FURI_LOG_E(
|
||||
TAG, "Update PHY failed, status %d", evt_le_phy_update_complete->Status);
|
||||
} else {
|
||||
FURI_LOG_I(TAG, "Update PHY succeed");
|
||||
}
|
||||
ret = hci_le_read_phy(gap->service.connection_handle, &tx_phy, &rx_phy);
|
||||
if(ret) {
|
||||
FURI_LOG_E(TAG, "Read PHY failed, status: %d", ret);
|
||||
} else {
|
||||
FURI_LOG_I(TAG, "PHY Params TX = %d, RX = %d ", tx_phy, rx_phy);
|
||||
}
|
||||
break;
|
||||
|
||||
case EVT_LE_CONN_COMPLETE:
|
||||
furi_hal_power_insomnia_enter();
|
||||
hci_le_connection_complete_event_rp0* connection_complete_event =
|
||||
(hci_le_connection_complete_event_rp0*)meta_evt->data;
|
||||
FURI_LOG_I(
|
||||
TAG,
|
||||
"Connection complete for connection handle 0x%x",
|
||||
connection_complete_event->Connection_Handle);
|
||||
|
||||
// Stop advertising as connection completed
|
||||
osTimerStop(gap->advertise_timer);
|
||||
|
||||
// Update connection status and handle
|
||||
gap->state = GapStateConnected;
|
||||
gap->service.connection_handle = connection_complete_event->Connection_Handle;
|
||||
|
||||
// Start pairing by sending security request
|
||||
aci_gap_slave_security_req(connection_complete_event->Connection_Handle);
|
||||
break;
|
||||
|
||||
case EVT_LE_ADVERTISING_REPORT: {
|
||||
if(gap_scan) {
|
||||
GapAddress address;
|
||||
hci_le_advertising_report_event_rp0* evt =
|
||||
(hci_le_advertising_report_event_rp0*)meta_evt->data;
|
||||
for(uint8_t i = 0; i < evt->Num_Reports; i++) {
|
||||
Advertising_Report_t* rep = &evt->Advertising_Report[i];
|
||||
address.type = rep->Address_Type;
|
||||
// Original MAC addres is in inverted order
|
||||
for(uint8_t j = 0; j < sizeof(address.mac); j++) {
|
||||
address.mac[j] = rep->Address[sizeof(address.mac) - j - 1];
|
||||
}
|
||||
gap_scan->callback(address, gap_scan->context);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case EVT_VENDOR:
|
||||
blue_evt = (evt_blue_aci*)event_pckt->data;
|
||||
switch(blue_evt->ecode) {
|
||||
aci_gap_pairing_complete_event_rp0* pairing_complete;
|
||||
|
||||
case EVT_BLUE_GAP_LIMITED_DISCOVERABLE:
|
||||
FURI_LOG_I(TAG, "Limited discoverable event");
|
||||
break;
|
||||
|
||||
case EVT_BLUE_GAP_PASS_KEY_REQUEST: {
|
||||
// Generate random PIN code
|
||||
uint32_t pin = rand() % 999999;
|
||||
aci_gap_pass_key_resp(gap->service.connection_handle, pin);
|
||||
FURI_LOG_I(TAG, "Pass key request event. Pin: %06d", pin);
|
||||
GapEvent event = {.type = GapEventTypePinCodeShow, .data.pin_code = pin};
|
||||
gap->on_event_cb(event, gap->context);
|
||||
} break;
|
||||
|
||||
case EVT_BLUE_ATT_EXCHANGE_MTU_RESP: {
|
||||
aci_att_exchange_mtu_resp_event_rp0* pr = (void*)blue_evt->data;
|
||||
FURI_LOG_I(TAG, "Rx MTU size: %d", pr->Server_RX_MTU);
|
||||
// Set maximum packet size given header size is 3 bytes
|
||||
GapEvent event = {
|
||||
.type = GapEventTypeUpdateMTU, .data.max_packet_size = pr->Server_RX_MTU - 3};
|
||||
gap->on_event_cb(event, gap->context);
|
||||
} break;
|
||||
|
||||
case EVT_BLUE_GAP_AUTHORIZATION_REQUEST:
|
||||
FURI_LOG_I(TAG, "Authorization request event");
|
||||
break;
|
||||
|
||||
case EVT_BLUE_GAP_SLAVE_SECURITY_INITIATED:
|
||||
FURI_LOG_I(TAG, "Slave security initiated");
|
||||
break;
|
||||
|
||||
case EVT_BLUE_GAP_BOND_LOST:
|
||||
FURI_LOG_I(TAG, "Bond lost event. Start rebonding");
|
||||
aci_gap_allow_rebond(gap->service.connection_handle);
|
||||
break;
|
||||
|
||||
case EVT_BLUE_GAP_DEVICE_FOUND:
|
||||
FURI_LOG_I(TAG, "Device found event");
|
||||
break;
|
||||
|
||||
case EVT_BLUE_GAP_ADDR_NOT_RESOLVED:
|
||||
FURI_LOG_I(TAG, "Address not resolved event");
|
||||
break;
|
||||
|
||||
case EVT_BLUE_GAP_KEYPRESS_NOTIFICATION:
|
||||
FURI_LOG_I(TAG, "Key press notification event");
|
||||
break;
|
||||
|
||||
case EVT_BLUE_GAP_NUMERIC_COMPARISON_VALUE: {
|
||||
uint32_t pin =
|
||||
((aci_gap_numeric_comparison_value_event_rp0*)(blue_evt->data))->Numeric_Value;
|
||||
FURI_LOG_I(TAG, "Verify numeric comparison: %06d", pin);
|
||||
GapEvent event = {.type = GapEventTypePinCodeVerify, .data.pin_code = pin};
|
||||
bool result = gap->on_event_cb(event, gap->context);
|
||||
aci_gap_numeric_comparison_value_confirm_yesno(gap->service.connection_handle, result);
|
||||
break;
|
||||
}
|
||||
|
||||
case EVT_BLUE_GAP_PAIRING_CMPLT:
|
||||
pairing_complete = (aci_gap_pairing_complete_event_rp0*)blue_evt->data;
|
||||
if(pairing_complete->Status) {
|
||||
FURI_LOG_E(
|
||||
TAG,
|
||||
"Pairing failed with status: %d. Terminating connection",
|
||||
pairing_complete->Status);
|
||||
aci_gap_terminate(gap->service.connection_handle, 5);
|
||||
} else {
|
||||
FURI_LOG_I(TAG, "Pairing complete");
|
||||
GapEvent event = {.type = GapEventTypeConnected};
|
||||
gap->on_event_cb(event, gap->context);
|
||||
}
|
||||
break;
|
||||
|
||||
case EVT_BLUE_GAP_PROCEDURE_COMPLETE:
|
||||
FURI_LOG_I(TAG, "Procedure complete event");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(gap) {
|
||||
osMutexRelease(gap->state_mutex);
|
||||
}
|
||||
return SVCCTL_UserEvtFlowEnable;
|
||||
}
|
||||
|
||||
static void set_advertisment_service_uid(uint8_t* uid, uint8_t uid_len) {
|
||||
if(uid_len == 2) {
|
||||
gap->service.adv_svc_uuid[0] = AD_TYPE_16_BIT_SERV_UUID;
|
||||
} else if(uid_len == 4) {
|
||||
gap->service.adv_svc_uuid[0] = AD_TYPE_32_BIT_SERV_UUID;
|
||||
} else if(uid_len == 16) {
|
||||
gap->service.adv_svc_uuid[0] = AD_TYPE_128_BIT_SERV_UUID_CMPLT_LIST;
|
||||
}
|
||||
memcpy(&gap->service.adv_svc_uuid[gap->service.adv_svc_uuid_len], uid, uid_len);
|
||||
gap->service.adv_svc_uuid_len += uid_len;
|
||||
}
|
||||
|
||||
static void gap_init_svc(Gap* gap) {
|
||||
tBleStatus status;
|
||||
uint32_t srd_bd_addr[2];
|
||||
|
||||
// HCI Reset to synchronise BLE Stack
|
||||
hci_reset();
|
||||
// Configure mac address
|
||||
aci_hal_write_config_data(
|
||||
CONFIG_DATA_PUBADDR_OFFSET, CONFIG_DATA_PUBADDR_LEN, gap->config->mac_address);
|
||||
|
||||
/* Static random Address
|
||||
* The two upper bits shall be set to 1
|
||||
* The lowest 32bits is read from the UDN to differentiate between devices
|
||||
* The RNG may be used to provide a random number on each power on
|
||||
*/
|
||||
srd_bd_addr[1] = 0x0000ED6E;
|
||||
srd_bd_addr[0] = LL_FLASH_GetUDN();
|
||||
aci_hal_write_config_data(
|
||||
CONFIG_DATA_RANDOM_ADDRESS_OFFSET, CONFIG_DATA_RANDOM_ADDRESS_LEN, (uint8_t*)srd_bd_addr);
|
||||
// Set Identity root key used to derive LTK and CSRK
|
||||
aci_hal_write_config_data(CONFIG_DATA_IR_OFFSET, CONFIG_DATA_IR_LEN, (uint8_t*)gap_irk);
|
||||
// Set Encryption root key used to derive LTK and CSRK
|
||||
aci_hal_write_config_data(CONFIG_DATA_ER_OFFSET, CONFIG_DATA_ER_LEN, (uint8_t*)gap_erk);
|
||||
// Set TX Power to 0 dBm
|
||||
aci_hal_set_tx_power_level(1, 0x19);
|
||||
// Initialize GATT interface
|
||||
aci_gatt_init();
|
||||
// Initialize GAP interface
|
||||
// Skip fist symbol AD_TYPE_COMPLETE_LOCAL_NAME
|
||||
char* name = gap->service.adv_name + 1;
|
||||
aci_gap_init(
|
||||
GAP_PERIPHERAL_ROLE,
|
||||
0,
|
||||
strlen(name),
|
||||
&gap->service.gap_svc_handle,
|
||||
&gap->service.dev_name_char_handle,
|
||||
&gap->service.appearance_char_handle);
|
||||
|
||||
// Set GAP characteristics
|
||||
status = aci_gatt_update_char_value(
|
||||
gap->service.gap_svc_handle,
|
||||
gap->service.dev_name_char_handle,
|
||||
0,
|
||||
strlen(name),
|
||||
(uint8_t*)name);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed updating name characteristic: %d", status);
|
||||
}
|
||||
uint8_t gap_appearence_char_uuid[2] = {
|
||||
gap->config->appearance_char & 0xff, gap->config->appearance_char >> 8};
|
||||
status = aci_gatt_update_char_value(
|
||||
gap->service.gap_svc_handle,
|
||||
gap->service.appearance_char_handle,
|
||||
0,
|
||||
2,
|
||||
gap_appearence_char_uuid);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed updating appearence characteristic: %d", status);
|
||||
}
|
||||
// Set default PHY
|
||||
hci_le_set_default_phy(ALL_PHYS_PREFERENCE, TX_2M_PREFERRED, RX_2M_PREFERRED);
|
||||
// Set I/O capability
|
||||
bool keypress_supported = false;
|
||||
if(gap->config->pairing_method == GapPairingPinCodeShow) {
|
||||
aci_gap_set_io_capability(IO_CAP_DISPLAY_ONLY);
|
||||
} else if(gap->config->pairing_method == GapPairingPinCodeVerifyYesNo) {
|
||||
aci_gap_set_io_capability(IO_CAP_DISPLAY_YES_NO);
|
||||
keypress_supported = true;
|
||||
}
|
||||
// Setup authentication
|
||||
aci_gap_set_authentication_requirement(
|
||||
gap->config->bonding_mode,
|
||||
CFG_MITM_PROTECTION,
|
||||
CFG_SC_SUPPORT,
|
||||
keypress_supported,
|
||||
CFG_ENCRYPTION_KEY_SIZE_MIN,
|
||||
CFG_ENCRYPTION_KEY_SIZE_MAX,
|
||||
CFG_USED_FIXED_PIN,
|
||||
0,
|
||||
PUBLIC_ADDR);
|
||||
// Configure whitelist
|
||||
aci_gap_configure_whitelist();
|
||||
}
|
||||
|
||||
static void gap_advertise_start(GapState new_state) {
|
||||
tBleStatus status;
|
||||
uint16_t min_interval;
|
||||
uint16_t max_interval;
|
||||
|
||||
if(new_state == GapStateAdvFast) {
|
||||
min_interval = 0x80; // 80 ms
|
||||
max_interval = 0xa0; // 100 ms
|
||||
} else {
|
||||
min_interval = 0x0640; // 1 s
|
||||
max_interval = 0x0fa0; // 2.5 s
|
||||
}
|
||||
// Stop advertising timer
|
||||
osTimerStop(gap->advertise_timer);
|
||||
|
||||
if((new_state == GapStateAdvLowPower) &&
|
||||
((gap->state == GapStateAdvFast) || (gap->state == GapStateAdvLowPower))) {
|
||||
// Stop advertising
|
||||
status = aci_gap_set_non_discoverable();
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Stop Advertising Failed, result: %d", status);
|
||||
}
|
||||
}
|
||||
// Configure advertising
|
||||
status = aci_gap_set_discoverable(
|
||||
ADV_IND,
|
||||
min_interval,
|
||||
max_interval,
|
||||
PUBLIC_ADDR,
|
||||
0,
|
||||
strlen(gap->service.adv_name),
|
||||
(uint8_t*)gap->service.adv_name,
|
||||
gap->service.adv_svc_uuid_len,
|
||||
gap->service.adv_svc_uuid,
|
||||
0,
|
||||
0);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Set discoverable err: %d", status);
|
||||
}
|
||||
gap->state = new_state;
|
||||
GapEvent event = {.type = GapEventTypeStartAdvertising};
|
||||
gap->on_event_cb(event, gap->context);
|
||||
osTimerStart(gap->advertise_timer, INITIAL_ADV_TIMEOUT);
|
||||
}
|
||||
|
||||
static void gap_advertise_stop() {
|
||||
if(gap->state > GapStateIdle) {
|
||||
if(gap->state == GapStateConnected) {
|
||||
// Terminate connection
|
||||
aci_gap_terminate(gap->service.connection_handle, 0x13);
|
||||
}
|
||||
// Stop advertising
|
||||
osTimerStop(gap->advertise_timer);
|
||||
aci_gap_set_non_discoverable();
|
||||
gap->state = GapStateIdle;
|
||||
}
|
||||
GapEvent event = {.type = GapEventTypeStopAdvertising};
|
||||
gap->on_event_cb(event, gap->context);
|
||||
}
|
||||
|
||||
void gap_start_advertising() {
|
||||
osMutexAcquire(gap->state_mutex, osWaitForever);
|
||||
if(gap->state == GapStateIdle) {
|
||||
gap->state = GapStateStartingAdv;
|
||||
FURI_LOG_I(TAG, "Start advertising");
|
||||
gap->enable_adv = true;
|
||||
GapCommand command = GapCommandAdvFast;
|
||||
furi_check(osMessageQueuePut(gap->command_queue, &command, 0, 0) == osOK);
|
||||
}
|
||||
osMutexRelease(gap->state_mutex);
|
||||
}
|
||||
|
||||
void gap_stop_advertising() {
|
||||
osMutexAcquire(gap->state_mutex, osWaitForever);
|
||||
if(gap->state > GapStateIdle) {
|
||||
FURI_LOG_I(TAG, "Stop advertising");
|
||||
gap->enable_adv = false;
|
||||
GapCommand command = GapCommandAdvStop;
|
||||
furi_check(osMessageQueuePut(gap->command_queue, &command, 0, 0) == osOK);
|
||||
}
|
||||
osMutexRelease(gap->state_mutex);
|
||||
}
|
||||
|
||||
static void gap_advetise_timer_callback(void* context) {
|
||||
GapCommand command = GapCommandAdvLowPower;
|
||||
furi_check(osMessageQueuePut(gap->command_queue, &command, 0, 0) == osOK);
|
||||
}
|
||||
|
||||
bool gap_init(GapConfig* config, GapEventCallback on_event_cb, void* context) {
|
||||
if(!ble_glue_is_radio_stack_ready()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
gap = furi_alloc(sizeof(Gap));
|
||||
gap->config = config;
|
||||
srand(DWT->CYCCNT);
|
||||
// Create advertising timer
|
||||
gap->advertise_timer = osTimerNew(gap_advetise_timer_callback, osTimerOnce, NULL, NULL);
|
||||
// Initialization of GATT & GAP layer
|
||||
gap->service.adv_name = config->adv_name;
|
||||
gap_init_svc(gap);
|
||||
// Initialization of the BLE Services
|
||||
SVCCTL_Init();
|
||||
// Initialization of the GAP state
|
||||
gap->state_mutex = osMutexNew(NULL);
|
||||
gap->state = GapStateIdle;
|
||||
gap->service.connection_handle = 0xFFFF;
|
||||
gap->enable_adv = true;
|
||||
|
||||
// Thread configuration
|
||||
gap->thread = furi_thread_alloc();
|
||||
furi_thread_set_name(gap->thread, "BleGapWorker");
|
||||
furi_thread_set_stack_size(gap->thread, 1024);
|
||||
furi_thread_set_context(gap->thread, gap);
|
||||
furi_thread_set_callback(gap->thread, gap_app);
|
||||
furi_thread_start(gap->thread);
|
||||
|
||||
// Command queue allocation
|
||||
gap->command_queue = osMessageQueueNew(8, sizeof(GapCommand), NULL);
|
||||
|
||||
uint8_t adv_service_uid[2];
|
||||
gap->service.adv_svc_uuid_len = 1;
|
||||
adv_service_uid[0] = gap->config->adv_service_uuid & 0xff;
|
||||
adv_service_uid[1] = gap->config->adv_service_uuid >> 8;
|
||||
set_advertisment_service_uid(adv_service_uid, sizeof(adv_service_uid));
|
||||
|
||||
// Set callback
|
||||
gap->on_event_cb = on_event_cb;
|
||||
gap->context = context;
|
||||
return true;
|
||||
}
|
||||
|
||||
GapState gap_get_state() {
|
||||
GapState state;
|
||||
if(gap) {
|
||||
osMutexAcquire(gap->state_mutex, osWaitForever);
|
||||
state = gap->state;
|
||||
osMutexRelease(gap->state_mutex);
|
||||
} else {
|
||||
state = GapStateUninitialized;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
void gap_start_scan(GapScanCallback callback, void* context) {
|
||||
furi_assert(callback);
|
||||
gap_scan = furi_alloc(sizeof(GapScan));
|
||||
gap_scan->callback = callback;
|
||||
gap_scan->context = context;
|
||||
// Scan interval 250 ms
|
||||
hci_le_set_scan_parameters(1, 4000, 200, 0, 0);
|
||||
hci_le_set_scan_enable(1, 1);
|
||||
}
|
||||
|
||||
void gap_stop_scan() {
|
||||
furi_assert(gap_scan);
|
||||
hci_le_set_scan_enable(0, 1);
|
||||
free(gap_scan);
|
||||
gap_scan = NULL;
|
||||
}
|
||||
|
||||
void gap_thread_stop() {
|
||||
if(gap) {
|
||||
osMutexAcquire(gap->state_mutex, osWaitForever);
|
||||
gap->enable_adv = false;
|
||||
GapCommand command = GapCommandKillThread;
|
||||
osMessageQueuePut(gap->command_queue, &command, 0, osWaitForever);
|
||||
osMutexRelease(gap->state_mutex);
|
||||
furi_thread_join(gap->thread);
|
||||
furi_thread_free(gap->thread);
|
||||
// Free resources
|
||||
osMutexDelete(gap->state_mutex);
|
||||
osMessageQueueDelete(gap->command_queue);
|
||||
osTimerStop(gap->advertise_timer);
|
||||
while(xTimerIsTimerActive(gap->advertise_timer) == pdTRUE) osDelay(1);
|
||||
furi_check(osTimerDelete(gap->advertise_timer) == osOK);
|
||||
free(gap);
|
||||
gap = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t gap_app(void* context) {
|
||||
GapCommand command;
|
||||
while(1) {
|
||||
osStatus_t status = osMessageQueueGet(gap->command_queue, &command, NULL, osWaitForever);
|
||||
if(status != osOK) {
|
||||
FURI_LOG_E(TAG, "Message queue get error: %d", status);
|
||||
continue;
|
||||
}
|
||||
osMutexAcquire(gap->state_mutex, osWaitForever);
|
||||
if(command == GapCommandKillThread) {
|
||||
break;
|
||||
}
|
||||
if(command == GapCommandAdvFast) {
|
||||
gap_advertise_start(GapStateAdvFast);
|
||||
} else if(command == GapCommandAdvLowPower) {
|
||||
gap_advertise_start(GapStateAdvLowPower);
|
||||
} else if(command == GapCommandAdvStop) {
|
||||
gap_advertise_stop();
|
||||
}
|
||||
osMutexRelease(gap->state_mutex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
83
firmware/targets/f6/ble_glue/gap.h
Normal file
83
firmware/targets/f6/ble_glue/gap.h
Normal file
@@ -0,0 +1,83 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <furi_hal_version.h>
|
||||
|
||||
#define GAP_MAC_ADDR_SIZE (6)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
GapEventTypeConnected,
|
||||
GapEventTypeDisconnected,
|
||||
GapEventTypeStartAdvertising,
|
||||
GapEventTypeStopAdvertising,
|
||||
GapEventTypePinCodeShow,
|
||||
GapEventTypePinCodeVerify,
|
||||
GapEventTypeUpdateMTU,
|
||||
} GapEventType;
|
||||
|
||||
typedef union {
|
||||
uint32_t pin_code;
|
||||
uint16_t max_packet_size;
|
||||
} GapEventData;
|
||||
|
||||
typedef struct {
|
||||
GapEventType type;
|
||||
GapEventData data;
|
||||
} GapEvent;
|
||||
|
||||
typedef bool (*GapEventCallback)(GapEvent event, void* context);
|
||||
|
||||
typedef struct {
|
||||
uint8_t type;
|
||||
uint8_t mac[6];
|
||||
} GapAddress;
|
||||
|
||||
typedef void (*GapScanCallback)(GapAddress address, void* context);
|
||||
|
||||
typedef enum {
|
||||
GapStateUninitialized,
|
||||
GapStateIdle,
|
||||
GapStateStartingAdv,
|
||||
GapStateAdvFast,
|
||||
GapStateAdvLowPower,
|
||||
GapStateConnected,
|
||||
} GapState;
|
||||
|
||||
typedef enum {
|
||||
GapPairingNone,
|
||||
GapPairingPinCodeShow,
|
||||
GapPairingPinCodeVerifyYesNo,
|
||||
} GapPairing;
|
||||
|
||||
typedef struct {
|
||||
uint16_t adv_service_uuid;
|
||||
uint16_t appearance_char;
|
||||
bool bonding_mode;
|
||||
GapPairing pairing_method;
|
||||
uint8_t mac_address[GAP_MAC_ADDR_SIZE];
|
||||
char adv_name[FURI_HAL_VERSION_DEVICE_NAME_LENGTH];
|
||||
} GapConfig;
|
||||
|
||||
bool gap_init(GapConfig* config, GapEventCallback on_event_cb, void* context);
|
||||
|
||||
void gap_start_advertising();
|
||||
|
||||
void gap_stop_advertising();
|
||||
|
||||
GapState gap_get_state();
|
||||
|
||||
void gap_thread_stop();
|
||||
|
||||
void gap_start_scan(GapScanCallback callback, void* context);
|
||||
|
||||
void gap_stop_scan();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
260
firmware/targets/f6/ble_glue/hid_service.c
Normal file
260
firmware/targets/f6/ble_glue/hid_service.c
Normal file
@@ -0,0 +1,260 @@
|
||||
#include "hid_service.h"
|
||||
#include "app_common.h"
|
||||
#include "ble.h"
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
#define TAG "BtHid"
|
||||
|
||||
typedef struct {
|
||||
uint16_t svc_handle;
|
||||
uint16_t protocol_mode_char_handle;
|
||||
uint16_t report_char_handle;
|
||||
uint16_t report_ref_desc_handle;
|
||||
uint16_t report_map_char_handle;
|
||||
uint16_t keyboard_boot_char_handle;
|
||||
uint16_t info_char_handle;
|
||||
uint16_t ctrl_point_char_handle;
|
||||
} HIDSvc;
|
||||
|
||||
static HIDSvc* hid_svc = NULL;
|
||||
|
||||
static SVCCTL_EvtAckStatus_t hid_svc_event_handler(void* event) {
|
||||
SVCCTL_EvtAckStatus_t ret = SVCCTL_EvtNotAck;
|
||||
hci_event_pckt* event_pckt = (hci_event_pckt*)(((hci_uart_pckt*)event)->data);
|
||||
evt_blecore_aci* blecore_evt = (evt_blecore_aci*)event_pckt->data;
|
||||
// aci_gatt_attribute_modified_event_rp0* attribute_modified;
|
||||
if(event_pckt->evt == HCI_VENDOR_SPECIFIC_DEBUG_EVT_CODE) {
|
||||
if(blecore_evt->ecode == ACI_GATT_ATTRIBUTE_MODIFIED_VSEVT_CODE) {
|
||||
// Process modification events
|
||||
ret = SVCCTL_EvtAckFlowEnable;
|
||||
} else if(blecore_evt->ecode == ACI_GATT_SERVER_CONFIRMATION_VSEVT_CODE) {
|
||||
// Process notification confirmation
|
||||
ret = SVCCTL_EvtAckFlowEnable;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void hid_svc_start() {
|
||||
tBleStatus status;
|
||||
hid_svc = furi_alloc(sizeof(HIDSvc));
|
||||
Service_UUID_t svc_uuid = {};
|
||||
Char_Desc_Uuid_t desc_uuid = {};
|
||||
Char_UUID_t char_uuid = {};
|
||||
|
||||
// Register event handler
|
||||
SVCCTL_RegisterSvcHandler(hid_svc_event_handler);
|
||||
// Add service
|
||||
svc_uuid.Service_UUID_16 = HUMAN_INTERFACE_DEVICE_SERVICE_UUID;
|
||||
status =
|
||||
aci_gatt_add_service(UUID_TYPE_16, &svc_uuid, PRIMARY_SERVICE, 30, &hid_svc->svc_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to add HID service: %d", status);
|
||||
}
|
||||
// Add Protocol mode characterstics
|
||||
char_uuid.Char_UUID_16 = PROTOCOL_MODE_CHAR_UUID;
|
||||
status = aci_gatt_add_char(
|
||||
hid_svc->svc_handle,
|
||||
UUID_TYPE_16,
|
||||
&char_uuid,
|
||||
1,
|
||||
CHAR_PROP_READ | CHAR_PROP_WRITE_WITHOUT_RESP,
|
||||
ATTR_PERMISSION_NONE,
|
||||
GATT_NOTIFY_ATTRIBUTE_WRITE,
|
||||
10,
|
||||
CHAR_VALUE_LEN_CONSTANT,
|
||||
&hid_svc->protocol_mode_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to add protocol mode characteristic: %d", status);
|
||||
}
|
||||
// Update Protocol mode characteristic
|
||||
uint8_t protocol_mode = 1;
|
||||
status = aci_gatt_update_char_value(
|
||||
hid_svc->svc_handle, hid_svc->protocol_mode_char_handle, 0, 1, &protocol_mode);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to update protocol mode characteristic: %d", status);
|
||||
}
|
||||
// Add Report characterstics
|
||||
char_uuid.Char_UUID_16 = REPORT_CHAR_UUID;
|
||||
status = aci_gatt_add_char(
|
||||
hid_svc->svc_handle,
|
||||
UUID_TYPE_16,
|
||||
&char_uuid,
|
||||
HID_SVC_REPORT_MAX_LEN,
|
||||
CHAR_PROP_READ | CHAR_PROP_NOTIFY,
|
||||
ATTR_PERMISSION_NONE,
|
||||
GATT_DONT_NOTIFY_EVENTS,
|
||||
10,
|
||||
CHAR_VALUE_LEN_VARIABLE,
|
||||
&hid_svc->report_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to add report characteristic: %d", status);
|
||||
}
|
||||
// Add Report descriptor
|
||||
uint8_t desc_val[] = {0x00, 0x01};
|
||||
desc_uuid.Char_UUID_16 = REPORT_REFERENCE_DESCRIPTOR_UUID;
|
||||
status = aci_gatt_add_char_desc(
|
||||
hid_svc->svc_handle,
|
||||
hid_svc->report_char_handle,
|
||||
UUID_TYPE_16,
|
||||
&desc_uuid,
|
||||
HID_SVC_REPORT_REF_LEN,
|
||||
HID_SVC_REPORT_REF_LEN,
|
||||
desc_val,
|
||||
ATTR_PERMISSION_NONE,
|
||||
ATTR_ACCESS_READ_ONLY,
|
||||
GATT_DONT_NOTIFY_EVENTS,
|
||||
MIN_ENCRY_KEY_SIZE,
|
||||
CHAR_VALUE_LEN_CONSTANT,
|
||||
&hid_svc->report_ref_desc_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to add report reference descriptor: %d", status);
|
||||
}
|
||||
// Add Report Map characteristic
|
||||
char_uuid.Char_UUID_16 = REPORT_MAP_CHAR_UUID;
|
||||
status = aci_gatt_add_char(
|
||||
hid_svc->svc_handle,
|
||||
UUID_TYPE_16,
|
||||
&char_uuid,
|
||||
HID_SVC_REPORT_MAP_MAX_LEN,
|
||||
CHAR_PROP_READ,
|
||||
ATTR_PERMISSION_NONE,
|
||||
GATT_DONT_NOTIFY_EVENTS,
|
||||
10,
|
||||
CHAR_VALUE_LEN_VARIABLE,
|
||||
&hid_svc->report_map_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to add report map characteristic: %d", status);
|
||||
}
|
||||
// Add Boot Keyboard characteristic
|
||||
char_uuid.Char_UUID_16 = BOOT_KEYBOARD_INPUT_REPORT_CHAR_UUID;
|
||||
status = aci_gatt_add_char(
|
||||
hid_svc->svc_handle,
|
||||
UUID_TYPE_16,
|
||||
&char_uuid,
|
||||
HID_SVC_BOOT_KEYBOARD_INPUT_REPORT_MAX_LEN,
|
||||
CHAR_PROP_READ | CHAR_PROP_NOTIFY,
|
||||
ATTR_PERMISSION_NONE,
|
||||
GATT_NOTIFY_WRITE_REQ_AND_WAIT_FOR_APPL_RESP,
|
||||
10,
|
||||
CHAR_VALUE_LEN_VARIABLE,
|
||||
&hid_svc->keyboard_boot_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to add report map characteristic: %d", status);
|
||||
}
|
||||
// Add Information characteristic
|
||||
char_uuid.Char_UUID_16 = HID_INFORMATION_CHAR_UUID;
|
||||
status = aci_gatt_add_char(
|
||||
hid_svc->svc_handle,
|
||||
UUID_TYPE_16,
|
||||
&char_uuid,
|
||||
HID_SVC_INFO_LEN,
|
||||
CHAR_PROP_READ,
|
||||
ATTR_PERMISSION_NONE,
|
||||
GATT_DONT_NOTIFY_EVENTS,
|
||||
10,
|
||||
CHAR_VALUE_LEN_CONSTANT,
|
||||
&hid_svc->info_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to add information characteristic: %d", status);
|
||||
}
|
||||
// Add Control Point characteristic
|
||||
char_uuid.Char_UUID_16 = HID_CONTROL_POINT_CHAR_UUID;
|
||||
status = aci_gatt_add_char(
|
||||
hid_svc->svc_handle,
|
||||
UUID_TYPE_16,
|
||||
&char_uuid,
|
||||
HID_SVC_CONTROL_POINT_LEN,
|
||||
CHAR_PROP_WRITE_WITHOUT_RESP,
|
||||
ATTR_PERMISSION_NONE,
|
||||
GATT_NOTIFY_ATTRIBUTE_WRITE,
|
||||
10,
|
||||
CHAR_VALUE_LEN_CONSTANT,
|
||||
&hid_svc->ctrl_point_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to add control point characteristic: %d", status);
|
||||
}
|
||||
}
|
||||
|
||||
bool hid_svc_update_report_map(uint8_t* data, uint16_t len) {
|
||||
furi_assert(data);
|
||||
furi_assert(hid_svc);
|
||||
|
||||
tBleStatus status = aci_gatt_update_char_value(
|
||||
hid_svc->svc_handle, hid_svc->report_map_char_handle, 0, len, data);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed updating report map characteristic");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool hid_svc_update_input_report(uint8_t* data, uint16_t len) {
|
||||
furi_assert(data);
|
||||
furi_assert(hid_svc);
|
||||
|
||||
tBleStatus status =
|
||||
aci_gatt_update_char_value(hid_svc->svc_handle, hid_svc->report_char_handle, 0, len, data);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed updating report characteristic");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool hid_svc_update_info(uint8_t* data, uint16_t len) {
|
||||
furi_assert(data);
|
||||
furi_assert(hid_svc);
|
||||
|
||||
tBleStatus status =
|
||||
aci_gatt_update_char_value(hid_svc->svc_handle, hid_svc->info_char_handle, 0, len, data);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed updating info characteristic");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool hid_svc_is_started() {
|
||||
return hid_svc != NULL;
|
||||
}
|
||||
|
||||
void hid_svc_stop() {
|
||||
tBleStatus status;
|
||||
if(hid_svc) {
|
||||
// Delete characteristics
|
||||
status = aci_gatt_del_char(hid_svc->svc_handle, hid_svc->report_map_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to delete Report Map characteristic: %d", status);
|
||||
}
|
||||
status = aci_gatt_del_char(hid_svc->svc_handle, hid_svc->report_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to delete Report characteristic: %d", status);
|
||||
}
|
||||
status = aci_gatt_del_char(hid_svc->svc_handle, hid_svc->protocol_mode_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to delete Protocol Mode characteristic: %d", status);
|
||||
}
|
||||
status = aci_gatt_del_char(hid_svc->svc_handle, hid_svc->keyboard_boot_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to delete Keyboard Boot characteristic: %d", status);
|
||||
}
|
||||
status = aci_gatt_del_char(hid_svc->svc_handle, hid_svc->info_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to delete Information characteristic: %d", status);
|
||||
}
|
||||
status = aci_gatt_del_char(hid_svc->svc_handle, hid_svc->ctrl_point_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to delete Control Point characteristic: %d", status);
|
||||
}
|
||||
// Delete service
|
||||
status = aci_gatt_del_service(hid_svc->svc_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to delete HID service: %d", status);
|
||||
}
|
||||
// Delete buffer size mutex
|
||||
free(hid_svc);
|
||||
hid_svc = NULL;
|
||||
}
|
||||
}
|
||||
23
firmware/targets/f6/ble_glue/hid_service.h
Normal file
23
firmware/targets/f6/ble_glue/hid_service.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define HID_SVC_REPORT_MAP_MAX_LEN (120)
|
||||
#define HID_SVC_REPORT_MAX_LEN (9)
|
||||
#define HID_SVC_BOOT_KEYBOARD_INPUT_REPORT_MAX_LEN (8)
|
||||
#define HID_SVC_REPORT_REF_LEN (2)
|
||||
#define HID_SVC_INFO_LEN (4)
|
||||
#define HID_SVC_CONTROL_POINT_LEN (1)
|
||||
|
||||
void hid_svc_start();
|
||||
|
||||
void hid_svc_stop();
|
||||
|
||||
bool hid_svc_is_started();
|
||||
|
||||
bool hid_svc_update_report_map(uint8_t* data, uint16_t len);
|
||||
|
||||
bool hid_svc_update_input_report(uint8_t* data, uint16_t len);
|
||||
|
||||
bool hid_svc_update_info(uint8_t* data, uint16_t len);
|
||||
231
firmware/targets/f6/ble_glue/hw_conf.h
Normal file
231
firmware/targets/f6/ble_glue/hw_conf.h
Normal file
@@ -0,0 +1,231 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file hw_conf.h
|
||||
* @author MCD Application Team
|
||||
* @brief Configuration of hardware interface
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2019 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 */
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef HW_CONF_H
|
||||
#define HW_CONF_H
|
||||
|
||||
#include "FreeRTOSConfig.h"
|
||||
|
||||
/******************************************************************************
|
||||
* Semaphores
|
||||
* THIS SHALL NO BE CHANGED AS THESE SEMAPHORES ARE USED AS WELL ON THE CM0+
|
||||
*****************************************************************************/
|
||||
/**
|
||||
* Index of the semaphore used the prevent conflicts after standby sleep.
|
||||
* Each CPUs takes this semaphore at standby wakeup until conclicting elements are restored.
|
||||
*/
|
||||
#define CFG_HW_PWR_STANDBY_SEMID 10
|
||||
/**
|
||||
* The CPU2 may be configured to store the Thread persistent data either in internal NVM storage on CPU2 or in
|
||||
* SRAM2 buffer provided by the user application. This can be configured with the system command SHCI_C2_Config()
|
||||
* When the CPU2 is requested to store persistent data in SRAM2, it can write data in this buffer at any time when needed.
|
||||
* In order to read consistent data with the CPU1 from the SRAM2 buffer, the flow should be:
|
||||
* + CPU1 takes CFG_HW_THREAD_NVM_SRAM_SEMID semaphore
|
||||
* + CPU1 reads all persistent data from SRAM2 (most of the time, the goal is to write these data into an NVM managed by CPU1)
|
||||
* + CPU1 releases CFG_HW_THREAD_NVM_SRAM_SEMID semaphore
|
||||
* CFG_HW_THREAD_NVM_SRAM_SEMID semaphore makes sure CPU2 does not update the persistent data in SRAM2 at the same time CPU1 is reading them.
|
||||
* There is no timing constraint on how long this semaphore can be kept.
|
||||
*/
|
||||
#define CFG_HW_THREAD_NVM_SRAM_SEMID 9
|
||||
|
||||
/**
|
||||
* The CPU2 may be configured to store the BLE persistent data either in internal NVM storage on CPU2 or in
|
||||
* SRAM2 buffer provided by the user application. This can be configured with the system command SHCI_C2_Config()
|
||||
* When the CPU2 is requested to store persistent data in SRAM2, it can write data in this buffer at any time when needed.
|
||||
* In order to read consistent data with the CPU1 from the SRAM2 buffer, the flow should be:
|
||||
* + CPU1 takes CFG_HW_BLE_NVM_SRAM_SEMID semaphore
|
||||
* + CPU1 reads all persistent data from SRAM2 (most of the time, the goal is to write these data into an NVM managed by CPU1)
|
||||
* + CPU1 releases CFG_HW_BLE_NVM_SRAM_SEMID semaphore
|
||||
* CFG_HW_BLE_NVM_SRAM_SEMID semaphore makes sure CPU2 does not update the persistent data in SRAM2 at the same time CPU1 is reading them.
|
||||
* There is no timing constraint on how long this semaphore can be kept.
|
||||
*/
|
||||
#define CFG_HW_BLE_NVM_SRAM_SEMID 8
|
||||
|
||||
/**
|
||||
* Index of the semaphore used by CPU2 to prevent the CPU1 to either write or erase data in flash
|
||||
* The CPU1 shall not either write or erase in flash when this semaphore is taken by the CPU2
|
||||
* When the CPU1 needs to either write or erase in flash, it shall first get the semaphore and release it just
|
||||
* after writing a raw (64bits data) or erasing one sector.
|
||||
* Once the Semaphore has been released, there shall be at least 1us before it can be taken again. This is required
|
||||
* to give the opportunity to CPU2 to take it.
|
||||
* On v1.4.0 and older CPU2 wireless firmware, this semaphore is unused and CPU2 is using PES bit.
|
||||
* By default, CPU2 is using the PES bit to protect its timing. The CPU1 may request the CPU2 to use the semaphore
|
||||
* instead of the PES bit by sending the system command SHCI_C2_SetFlashActivityControl()
|
||||
*/
|
||||
#define CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID 7
|
||||
|
||||
/**
|
||||
* Index of the semaphore used by CPU1 to prevent the CPU2 to either write or erase data in flash
|
||||
* In order to protect its timing, the CPU1 may get this semaphore to prevent the CPU2 to either
|
||||
* write or erase in flash (as this will stall both CPUs)
|
||||
* The PES bit shall not be used as this may stall the CPU2 in some cases.
|
||||
*/
|
||||
#define CFG_HW_BLOCK_FLASH_REQ_BY_CPU1_SEMID 6
|
||||
|
||||
/**
|
||||
* Index of the semaphore used to manage the CLK48 clock configuration
|
||||
* When the USB is required, this semaphore shall be taken before configuring te CLK48 for USB
|
||||
* and should be released after the application switch OFF the clock when the USB is not used anymore
|
||||
* When using the RNG, it is good enough to use CFG_HW_RNG_SEMID to control CLK48.
|
||||
* More details in AN5289
|
||||
*/
|
||||
#define CFG_HW_CLK48_CONFIG_SEMID 5
|
||||
|
||||
/* Index of the semaphore used to manage the entry Stop Mode procedure */
|
||||
#define CFG_HW_ENTRY_STOP_MODE_SEMID 4
|
||||
|
||||
/* Index of the semaphore used to access the RCC */
|
||||
#define CFG_HW_RCC_SEMID 3
|
||||
|
||||
/* Index of the semaphore used to access the FLASH */
|
||||
#define CFG_HW_FLASH_SEMID 2
|
||||
|
||||
/* Index of the semaphore used to access the PKA */
|
||||
#define CFG_HW_PKA_SEMID 1
|
||||
|
||||
/* Index of the semaphore used to access the RNG */
|
||||
#define CFG_HW_RNG_SEMID 0
|
||||
|
||||
/******************************************************************************
|
||||
* HW TIMER SERVER
|
||||
*****************************************************************************/
|
||||
/**
|
||||
* The user may define the maximum number of virtual timers supported.
|
||||
* It shall not exceed 255
|
||||
*/
|
||||
#define CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER 6
|
||||
|
||||
/**
|
||||
* The user may define the priority in the NVIC of the RTC_WKUP interrupt handler that is used to manage the
|
||||
* wakeup timer.
|
||||
* This setting is the preemptpriority part of the NVIC.
|
||||
*/
|
||||
#define CFG_HW_TS_NVIC_RTC_WAKEUP_IT_PREEMPTPRIO \
|
||||
(configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1) /* FreeRTOS requirement */
|
||||
|
||||
/**
|
||||
* The user may define the priority in the NVIC of the RTC_WKUP interrupt handler that is used to manage the
|
||||
* wakeup timer.
|
||||
* This setting is the subpriority part of the NVIC. It does not exist on all processors. When it is not supported
|
||||
* on the CPU, the setting is ignored
|
||||
*/
|
||||
#define CFG_HW_TS_NVIC_RTC_WAKEUP_IT_SUBPRIO 0
|
||||
|
||||
/**
|
||||
* Define a critical section in the Timer server
|
||||
* The Timer server does not support the API to be nested
|
||||
* The Application shall either:
|
||||
* a) Ensure this will never happen
|
||||
* b) Define the critical section
|
||||
* The default implementations is masking all interrupts using the PRIMASK bit
|
||||
* The TimerServer driver uses critical sections to avoid context corruption. This is achieved with the macro
|
||||
* TIMER_ENTER_CRITICAL_SECTION and TIMER_EXIT_CRITICAL_SECTION. When CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION is set
|
||||
* to 1, all STM32 interrupts are masked with the PRIMASK bit of the CortexM CPU. It is possible to use the BASEPRI
|
||||
* register of the CortexM CPU to keep allowed some interrupts with high priority. In that case, the user shall
|
||||
* re-implement TIMER_ENTER_CRITICAL_SECTION and TIMER_EXIT_CRITICAL_SECTION and shall make sure that no TimerServer
|
||||
* API are called when the TIMER critical section is entered
|
||||
*/
|
||||
#define CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION 1
|
||||
|
||||
/**
|
||||
* This value shall reflect the maximum delay there could be in the application between the time the RTC interrupt
|
||||
* is generated by the Hardware and the time when the RTC interrupt handler is called. This time is measured in
|
||||
* number of RTCCLK ticks.
|
||||
* A relaxed timing would be 10ms
|
||||
* When the value is too short, the timerserver will not be able to count properly and all timeout may be random.
|
||||
* When the value is too long, the device may wake up more often than the most optimal configuration. However, the
|
||||
* impact on power consumption would be marginal (unless the value selected is extremely too long). It is strongly
|
||||
* recommended to select a value large enough to make sure it is not too short to ensure reliability of the system
|
||||
* as this will have marginal impact on low power mode
|
||||
*/
|
||||
#define CFG_HW_TS_RTC_HANDLER_MAX_DELAY (10 * (LSI_VALUE / 1000))
|
||||
|
||||
/**
|
||||
* Interrupt ID in the NVIC of the RTC Wakeup interrupt handler
|
||||
* It shall be type of IRQn_Type
|
||||
*/
|
||||
#define CFG_HW_TS_RTC_WAKEUP_HANDLER_ID RTC_WKUP_IRQn
|
||||
|
||||
/******************************************************************************
|
||||
* HW UART
|
||||
*****************************************************************************/
|
||||
#define CFG_HW_LPUART1_ENABLED 0
|
||||
#define CFG_HW_LPUART1_DMA_TX_SUPPORTED 0
|
||||
|
||||
#define CFG_HW_USART1_ENABLED 1
|
||||
#define CFG_HW_USART1_DMA_TX_SUPPORTED 1
|
||||
|
||||
/**
|
||||
* UART1
|
||||
*/
|
||||
#define CFG_HW_USART1_PREEMPTPRIORITY 0x0F
|
||||
#define CFG_HW_USART1_SUBPRIORITY 0
|
||||
|
||||
/** < The application shall check the selected source clock is enable */
|
||||
#define CFG_HW_USART1_SOURCE_CLOCK RCC_USART1CLKSOURCE_SYSCLK
|
||||
|
||||
#define CFG_HW_USART1_BAUDRATE 115200
|
||||
#define CFG_HW_USART1_WORDLENGTH UART_WORDLENGTH_8B
|
||||
#define CFG_HW_USART1_STOPBITS UART_STOPBITS_1
|
||||
#define CFG_HW_USART1_PARITY UART_PARITY_NONE
|
||||
#define CFG_HW_USART1_HWFLOWCTL UART_HWCONTROL_NONE
|
||||
#define CFG_HW_USART1_MODE UART_MODE_TX_RX
|
||||
#define CFG_HW_USART1_ADVFEATUREINIT UART_ADVFEATURE_NO_INIT
|
||||
#define CFG_HW_USART1_OVERSAMPLING UART_OVERSAMPLING_8
|
||||
|
||||
#define CFG_HW_USART1_TX_PORT_CLK_ENABLE __HAL_RCC_GPIOB_CLK_ENABLE
|
||||
#define CFG_HW_USART1_TX_PORT GPIOB
|
||||
#define CFG_HW_USART1_TX_PIN GPIO_PIN_6
|
||||
#define CFG_HW_USART1_TX_MODE GPIO_MODE_AF_PP
|
||||
#define CFG_HW_USART1_TX_PULL GPIO_NOPULL
|
||||
#define CFG_HW_USART1_TX_SPEED GPIO_SPEED_FREQ_VERY_HIGH
|
||||
#define CFG_HW_USART1_TX_ALTERNATE GPIO_AF7_USART1
|
||||
|
||||
#define CFG_HW_USART1_RX_PORT_CLK_ENABLE __HAL_RCC_GPIOB_CLK_ENABLE
|
||||
#define CFG_HW_USART1_RX_PORT GPIOB
|
||||
#define CFG_HW_USART1_RX_PIN GPIO_PIN_7
|
||||
#define CFG_HW_USART1_RX_MODE GPIO_MODE_AF_PP
|
||||
#define CFG_HW_USART1_RX_PULL GPIO_NOPULL
|
||||
#define CFG_HW_USART1_RX_SPEED GPIO_SPEED_FREQ_VERY_HIGH
|
||||
#define CFG_HW_USART1_RX_ALTERNATE GPIO_AF7_USART1
|
||||
|
||||
#define CFG_HW_USART1_CTS_PORT_CLK_ENABLE __HAL_RCC_GPIOA_CLK_ENABLE
|
||||
#define CFG_HW_USART1_CTS_PORT GPIOA
|
||||
#define CFG_HW_USART1_CTS_PIN GPIO_PIN_11
|
||||
#define CFG_HW_USART1_CTS_MODE GPIO_MODE_AF_PP
|
||||
#define CFG_HW_USART1_CTS_PULL GPIO_PULLDOWN
|
||||
#define CFG_HW_USART1_CTS_SPEED GPIO_SPEED_FREQ_VERY_HIGH
|
||||
#define CFG_HW_USART1_CTS_ALTERNATE GPIO_AF7_USART1
|
||||
|
||||
#define CFG_HW_USART1_DMA_TX_PREEMPTPRIORITY 0x0F
|
||||
#define CFG_HW_USART1_DMA_TX_SUBPRIORITY 0
|
||||
|
||||
#define CFG_HW_USART1_DMAMUX_CLK_ENABLE __HAL_RCC_DMAMUX1_CLK_ENABLE
|
||||
#define CFG_HW_USART1_DMA_CLK_ENABLE __HAL_RCC_DMA2_CLK_ENABLE
|
||||
#define CFG_HW_USART1_TX_DMA_REQ DMA_REQUEST_USART1_TX
|
||||
#define CFG_HW_USART1_TX_DMA_CHANNEL DMA2_Channel4
|
||||
#define CFG_HW_USART1_TX_DMA_IRQn DMA2_Channel4_IRQn
|
||||
#define CFG_HW_USART1_DMA_TX_IRQHandler DMA2_Channel4_IRQHandler
|
||||
|
||||
#endif /*HW_CONF_H */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
102
firmware/targets/f6/ble_glue/hw_if.h
Normal file
102
firmware/targets/f6/ble_glue/hw_if.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file hw_if.h
|
||||
* @author MCD Application Team
|
||||
* @brief Hardware Interface
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2019 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 */
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef HW_IF_H
|
||||
#define HW_IF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32wbxx.h"
|
||||
#include "stm32wbxx_ll_exti.h"
|
||||
#include "stm32wbxx_ll_system.h"
|
||||
#include "stm32wbxx_ll_rcc.h"
|
||||
#include "stm32wbxx_ll_ipcc.h"
|
||||
#include "stm32wbxx_ll_bus.h"
|
||||
#include "stm32wbxx_ll_pwr.h"
|
||||
#include "stm32wbxx_ll_cortex.h"
|
||||
#include "stm32wbxx_ll_utils.h"
|
||||
#include "stm32wbxx_ll_hsem.h"
|
||||
#include "stm32wbxx_ll_gpio.h"
|
||||
#include "stm32wbxx_ll_rtc.h"
|
||||
|
||||
#ifdef USE_STM32WBXX_USB_DONGLE
|
||||
#include "stm32wbxx_usb_dongle.h"
|
||||
#endif
|
||||
#ifdef USE_STM32WBXX_NUCLEO
|
||||
#include "stm32wbxx_nucleo.h"
|
||||
#endif
|
||||
#ifdef USE_X_NUCLEO_EPD
|
||||
#include "x_nucleo_epd.h"
|
||||
#endif
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/******************************************************************************
|
||||
* HW UART
|
||||
******************************************************************************/
|
||||
typedef enum {
|
||||
hw_uart1,
|
||||
hw_uart2,
|
||||
hw_lpuart1,
|
||||
} hw_uart_id_t;
|
||||
|
||||
typedef enum {
|
||||
hw_uart_ok,
|
||||
hw_uart_error,
|
||||
hw_uart_busy,
|
||||
hw_uart_to,
|
||||
} hw_status_t;
|
||||
|
||||
void HW_UART_Init(hw_uart_id_t hw_uart_id);
|
||||
void HW_UART_Receive_IT(
|
||||
hw_uart_id_t hw_uart_id,
|
||||
uint8_t* pData,
|
||||
uint16_t Size,
|
||||
void (*Callback)(void));
|
||||
void HW_UART_Transmit_IT(
|
||||
hw_uart_id_t hw_uart_id,
|
||||
uint8_t* pData,
|
||||
uint16_t Size,
|
||||
void (*Callback)(void));
|
||||
hw_status_t
|
||||
HW_UART_Transmit(hw_uart_id_t hw_uart_id, uint8_t* p_data, uint16_t size, uint32_t timeout);
|
||||
hw_status_t HW_UART_Transmit_DMA(
|
||||
hw_uart_id_t hw_uart_id,
|
||||
uint8_t* p_data,
|
||||
uint16_t size,
|
||||
void (*Callback)(void));
|
||||
void HW_UART_Interrupt_Handler(hw_uart_id_t hw_uart_id);
|
||||
void HW_UART_DMA_Interrupt_Handler(hw_uart_id_t hw_uart_id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*HW_IF_H */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
597
firmware/targets/f6/ble_glue/hw_ipcc.c
Normal file
597
firmware/targets/f6/ble_glue/hw_ipcc.c
Normal file
@@ -0,0 +1,597 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : Target/hw_ipcc.c
|
||||
* Description : Hardware IPCC source file for STM32WPAN Middleware.
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2020 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
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "app_common.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
|
||||
|
||||
#ifdef LLD_TESTS_WB
|
||||
static void HW_IPCC_LLDTESTS_ReceiveCliRspHandler(void);
|
||||
static void HW_IPCC_LLDTESTS_ReceiveM0CmdHandler(void);
|
||||
#endif
|
||||
#ifdef LLD_BLE_WB
|
||||
/*static void HW_IPCC_LLD_BLE_ReceiveCliRspHandler( void );*/
|
||||
static void HW_IPCC_LLD_BLE_ReceiveRspHandler(void);
|
||||
static void HW_IPCC_LLD_BLE_ReceiveM0CmdHandler(void);
|
||||
#endif
|
||||
|
||||
#ifdef MAC_802_15_4_WB
|
||||
static void HW_IPCC_MAC_802_15_4_CmdEvtHandler(void);
|
||||
static void HW_IPCC_MAC_802_15_4_NotEvtHandler(void);
|
||||
#endif
|
||||
|
||||
#ifdef ZIGBEE_WB
|
||||
static void HW_IPCC_ZIGBEE_CmdEvtHandler(void);
|
||||
static void HW_IPCC_ZIGBEE_StackNotifEvtHandler(void);
|
||||
static void HW_IPCC_ZIGBEE_StackM0RequestHandler(void);
|
||||
#endif
|
||||
|
||||
/* Public function definition -----------------------------------------------*/
|
||||
|
||||
/******************************************************************************
|
||||
* INTERRUPT HANDLER
|
||||
******************************************************************************/
|
||||
void HW_IPCC_Rx_Handler(void) {
|
||||
if(HW_IPCC_RX_PENDING(HW_IPCC_SYSTEM_EVENT_CHANNEL)) {
|
||||
HW_IPCC_SYS_EvtHandler();
|
||||
}
|
||||
#ifdef MAC_802_15_4_WB
|
||||
else if(HW_IPCC_RX_PENDING(HW_IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL)) {
|
||||
HW_IPCC_MAC_802_15_4_NotEvtHandler();
|
||||
}
|
||||
#endif /* MAC_802_15_4_WB */
|
||||
#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 */
|
||||
#ifdef LLD_TESTS_WB
|
||||
else if(HW_IPCC_RX_PENDING(HW_IPCC_LLDTESTS_CLI_RSP_CHANNEL)) {
|
||||
HW_IPCC_LLDTESTS_ReceiveCliRspHandler();
|
||||
} else if(HW_IPCC_RX_PENDING(HW_IPCC_LLDTESTS_M0_CMD_CHANNEL)) {
|
||||
HW_IPCC_LLDTESTS_ReceiveM0CmdHandler();
|
||||
}
|
||||
#endif /* LLD_TESTS_WB */
|
||||
#ifdef LLD_BLE_WB
|
||||
else if(HW_IPCC_RX_PENDING(HW_IPCC_LLD_BLE_RSP_CHANNEL)) {
|
||||
HW_IPCC_LLD_BLE_ReceiveRspHandler();
|
||||
} else if(HW_IPCC_RX_PENDING(HW_IPCC_LLD_BLE_M0_CMD_CHANNEL)) {
|
||||
HW_IPCC_LLD_BLE_ReceiveM0CmdHandler();
|
||||
}
|
||||
#endif /* LLD_TESTS_WB */
|
||||
#ifdef ZIGBEE_WB
|
||||
else if(HW_IPCC_RX_PENDING(HW_IPCC_ZIGBEE_APPLI_NOTIF_ACK_CHANNEL)) {
|
||||
HW_IPCC_ZIGBEE_StackNotifEvtHandler();
|
||||
} else if(HW_IPCC_RX_PENDING(HW_IPCC_ZIGBEE_M0_REQUEST_CHANNEL)) {
|
||||
HW_IPCC_ZIGBEE_StackM0RequestHandler();
|
||||
}
|
||||
#endif /* ZIGBEE_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();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_IPCC_Tx_Handler(void) {
|
||||
if(HW_IPCC_TX_PENDING(HW_IPCC_SYSTEM_CMD_RSP_CHANNEL)) {
|
||||
HW_IPCC_SYS_CmdEvtHandler();
|
||||
}
|
||||
#ifdef MAC_802_15_4_WB
|
||||
else if(HW_IPCC_TX_PENDING(HW_IPCC_MAC_802_15_4_CMD_RSP_CHANNEL)) {
|
||||
HW_IPCC_MAC_802_15_4_CmdEvtHandler();
|
||||
}
|
||||
#endif /* MAC_802_15_4_WB */
|
||||
#ifdef THREAD_WB
|
||||
else if(HW_IPCC_TX_PENDING(HW_IPCC_THREAD_OT_CMD_RSP_CHANNEL)) {
|
||||
HW_IPCC_OT_CmdEvtHandler();
|
||||
}
|
||||
#endif /* THREAD_WB */
|
||||
#ifdef LLD_TESTS_WB
|
||||
// No TX handler for LLD tests
|
||||
#endif /* LLD_TESTS_WB */
|
||||
#ifdef ZIGBEE_WB
|
||||
if(HW_IPCC_TX_PENDING(HW_IPCC_ZIGBEE_CMD_APPLI_CHANNEL)) {
|
||||
HW_IPCC_ZIGBEE_CmdEvtHandler();
|
||||
}
|
||||
#endif /* ZIGBEE_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();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
/******************************************************************************
|
||||
* 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_SetPriority(IPCC_C1_RX_IRQn, 6, 0);
|
||||
HAL_NVIC_EnableIRQ(IPCC_C1_RX_IRQn);
|
||||
HAL_NVIC_SetPriority(IPCC_C1_TX_IRQn, 6, 0);
|
||||
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){};
|
||||
|
||||
/******************************************************************************
|
||||
* MAC 802.15.4
|
||||
******************************************************************************/
|
||||
#ifdef MAC_802_15_4_WB
|
||||
void HW_IPCC_MAC_802_15_4_Init(void) {
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_IPCC_MAC_802_15_4_SendCmd(void) {
|
||||
LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_MAC_802_15_4_CMD_RSP_CHANNEL);
|
||||
LL_C1_IPCC_EnableTransmitChannel(IPCC, HW_IPCC_MAC_802_15_4_CMD_RSP_CHANNEL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_IPCC_MAC_802_15_4_SendAck(void) {
|
||||
LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL);
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void HW_IPCC_MAC_802_15_4_CmdEvtHandler(void) {
|
||||
LL_C1_IPCC_DisableTransmitChannel(IPCC, HW_IPCC_MAC_802_15_4_CMD_RSP_CHANNEL);
|
||||
|
||||
HW_IPCC_MAC_802_15_4_CmdEvtNot();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void HW_IPCC_MAC_802_15_4_NotEvtHandler(void) {
|
||||
LL_C1_IPCC_DisableReceiveChannel(IPCC, HW_IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL);
|
||||
|
||||
HW_IPCC_MAC_802_15_4_EvtNot();
|
||||
|
||||
return;
|
||||
}
|
||||
__weak void HW_IPCC_MAC_802_15_4_CmdEvtNot(void){};
|
||||
__weak void HW_IPCC_MAC_802_15_4_EvtNot(void){};
|
||||
#endif
|
||||
|
||||
/******************************************************************************
|
||||
* 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 */
|
||||
|
||||
/******************************************************************************
|
||||
* LLD TESTS
|
||||
******************************************************************************/
|
||||
#ifdef LLD_TESTS_WB
|
||||
void HW_IPCC_LLDTESTS_Init(void) {
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_LLDTESTS_CLI_RSP_CHANNEL);
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_LLDTESTS_M0_CMD_CHANNEL);
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_IPCC_LLDTESTS_SendCliCmd(void) {
|
||||
LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_LLDTESTS_CLI_CMD_CHANNEL);
|
||||
return;
|
||||
}
|
||||
|
||||
static void HW_IPCC_LLDTESTS_ReceiveCliRspHandler(void) {
|
||||
LL_C1_IPCC_DisableReceiveChannel(IPCC, HW_IPCC_LLDTESTS_CLI_RSP_CHANNEL);
|
||||
HW_IPCC_LLDTESTS_ReceiveCliRsp();
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_IPCC_LLDTESTS_SendCliRspAck(void) {
|
||||
LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_LLDTESTS_CLI_RSP_CHANNEL);
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_LLDTESTS_CLI_RSP_CHANNEL);
|
||||
return;
|
||||
}
|
||||
|
||||
static void HW_IPCC_LLDTESTS_ReceiveM0CmdHandler(void) {
|
||||
LL_C1_IPCC_DisableReceiveChannel(IPCC, HW_IPCC_LLDTESTS_M0_CMD_CHANNEL);
|
||||
HW_IPCC_LLDTESTS_ReceiveM0Cmd();
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_IPCC_LLDTESTS_SendM0CmdAck(void) {
|
||||
LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_LLDTESTS_M0_CMD_CHANNEL);
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_LLDTESTS_M0_CMD_CHANNEL);
|
||||
return;
|
||||
}
|
||||
__weak void HW_IPCC_LLDTESTS_ReceiveCliRsp(void){};
|
||||
__weak void HW_IPCC_LLDTESTS_ReceiveM0Cmd(void){};
|
||||
#endif /* LLD_TESTS_WB */
|
||||
|
||||
/******************************************************************************
|
||||
* LLD BLE
|
||||
******************************************************************************/
|
||||
#ifdef LLD_BLE_WB
|
||||
void HW_IPCC_LLD_BLE_Init(void) {
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_LLD_BLE_RSP_CHANNEL);
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_LLD_BLE_M0_CMD_CHANNEL);
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_IPCC_LLD_BLE_SendCliCmd(void) {
|
||||
LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_LLD_BLE_CLI_CMD_CHANNEL);
|
||||
return;
|
||||
}
|
||||
|
||||
/*static void HW_IPCC_LLD_BLE_ReceiveCliRspHandler( void )
|
||||
{
|
||||
LL_C1_IPCC_DisableReceiveChannel( IPCC, HW_IPCC_LLD_BLE_CLI_RSP_CHANNEL );
|
||||
HW_IPCC_LLD_BLE_ReceiveCliRsp();
|
||||
return;
|
||||
}*/
|
||||
|
||||
void HW_IPCC_LLD_BLE_SendCliRspAck(void) {
|
||||
LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_LLD_BLE_CLI_RSP_CHANNEL);
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_LLD_BLE_CLI_RSP_CHANNEL);
|
||||
return;
|
||||
}
|
||||
|
||||
static void HW_IPCC_LLD_BLE_ReceiveM0CmdHandler(void) {
|
||||
//LL_C1_IPCC_DisableReceiveChannel( IPCC, HW_IPCC_LLD_BLE_M0_CMD_CHANNEL );
|
||||
HW_IPCC_LLD_BLE_ReceiveM0Cmd();
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_IPCC_LLD_BLE_SendM0CmdAck(void) {
|
||||
LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_LLD_BLE_M0_CMD_CHANNEL);
|
||||
//LL_C1_IPCC_EnableReceiveChannel( IPCC, HW_IPCC_LLD_BLE_M0_CMD_CHANNEL );
|
||||
return;
|
||||
}
|
||||
__weak void HW_IPCC_LLD_BLE_ReceiveCliRsp(void){};
|
||||
__weak void HW_IPCC_LLD_BLE_ReceiveM0Cmd(void){};
|
||||
|
||||
/* Transparent Mode */
|
||||
void HW_IPCC_LLD_BLE_SendCmd(void) {
|
||||
LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_LLD_BLE_CMD_CHANNEL);
|
||||
return;
|
||||
}
|
||||
|
||||
static void HW_IPCC_LLD_BLE_ReceiveRspHandler(void) {
|
||||
LL_C1_IPCC_DisableReceiveChannel(IPCC, HW_IPCC_LLD_BLE_RSP_CHANNEL);
|
||||
HW_IPCC_LLD_BLE_ReceiveRsp();
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_IPCC_LLD_BLE_SendRspAck(void) {
|
||||
LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_LLD_BLE_RSP_CHANNEL);
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_LLD_BLE_RSP_CHANNEL);
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* LLD_BLE_WB */
|
||||
|
||||
/******************************************************************************
|
||||
* ZIGBEE
|
||||
******************************************************************************/
|
||||
#ifdef ZIGBEE_WB
|
||||
void HW_IPCC_ZIGBEE_Init(void) {
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_ZIGBEE_APPLI_NOTIF_ACK_CHANNEL);
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_ZIGBEE_M0_REQUEST_CHANNEL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_IPCC_ZIGBEE_SendM4RequestToM0(void) {
|
||||
LL_C1_IPCC_SetFlag_CHx(IPCC, HW_IPCC_ZIGBEE_CMD_APPLI_CHANNEL);
|
||||
LL_C1_IPCC_EnableTransmitChannel(IPCC, HW_IPCC_ZIGBEE_CMD_APPLI_CHANNEL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_IPCC_ZIGBEE_SendM4AckToM0Notify(void) {
|
||||
LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_ZIGBEE_APPLI_NOTIF_ACK_CHANNEL);
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_ZIGBEE_APPLI_NOTIF_ACK_CHANNEL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void HW_IPCC_ZIGBEE_CmdEvtHandler(void) {
|
||||
LL_C1_IPCC_DisableTransmitChannel(IPCC, HW_IPCC_ZIGBEE_CMD_APPLI_CHANNEL);
|
||||
|
||||
HW_IPCC_ZIGBEE_RecvAppliAckFromM0();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void HW_IPCC_ZIGBEE_StackNotifEvtHandler(void) {
|
||||
LL_C1_IPCC_DisableReceiveChannel(IPCC, HW_IPCC_ZIGBEE_APPLI_NOTIF_ACK_CHANNEL);
|
||||
|
||||
HW_IPCC_ZIGBEE_RecvM0NotifyToM4();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void HW_IPCC_ZIGBEE_StackM0RequestHandler(void) {
|
||||
LL_C1_IPCC_DisableReceiveChannel(IPCC, HW_IPCC_ZIGBEE_M0_REQUEST_CHANNEL);
|
||||
|
||||
HW_IPCC_ZIGBEE_RecvM0RequestToM4();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void HW_IPCC_ZIGBEE_SendM4AckToM0Request(void) {
|
||||
LL_C1_IPCC_ClearFlag_CHx(IPCC, HW_IPCC_ZIGBEE_M0_REQUEST_CHANNEL);
|
||||
LL_C1_IPCC_EnableReceiveChannel(IPCC, HW_IPCC_ZIGBEE_M0_REQUEST_CHANNEL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
__weak void HW_IPCC_ZIGBEE_RecvAppliAckFromM0(void){};
|
||||
__weak void HW_IPCC_ZIGBEE_RecvM0NotifyToM4(void){};
|
||||
__weak void HW_IPCC_ZIGBEE_RecvM0RequestToM4(void){};
|
||||
#endif /* ZIGBEE_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){};
|
||||
|
||||
/******************* (C) COPYRIGHT 2019 STMicroelectronics *****END OF FILE****/
|
||||
242
firmware/targets/f6/ble_glue/serial_service.c
Normal file
242
firmware/targets/f6/ble_glue/serial_service.c
Normal file
@@ -0,0 +1,242 @@
|
||||
#include "serial_service.h"
|
||||
#include "app_common.h"
|
||||
#include "ble.h"
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
#define TAG "BtSerialSvc"
|
||||
|
||||
typedef struct {
|
||||
uint16_t svc_handle;
|
||||
uint16_t rx_char_handle;
|
||||
uint16_t tx_char_handle;
|
||||
uint16_t flow_ctrl_char_handle;
|
||||
osMutexId_t buff_size_mtx;
|
||||
uint32_t buff_size;
|
||||
uint16_t bytes_ready_to_receive;
|
||||
SerialServiceEventCallback callback;
|
||||
void* context;
|
||||
} SerialSvc;
|
||||
|
||||
static SerialSvc* serial_svc = NULL;
|
||||
|
||||
static const uint8_t service_uuid[] =
|
||||
{0x00, 0x00, 0xfe, 0x60, 0xcc, 0x7a, 0x48, 0x2a, 0x98, 0x4a, 0x7f, 0x2e, 0xd5, 0xb3, 0xe5, 0x8f};
|
||||
static const uint8_t char_tx_uuid[] =
|
||||
{0x00, 0x00, 0xfe, 0x61, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19};
|
||||
static const uint8_t char_rx_uuid[] =
|
||||
{0x00, 0x00, 0xfe, 0x62, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19};
|
||||
static const uint8_t flow_ctrl_uuid[] =
|
||||
{0x00, 0x00, 0xfe, 0x63, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19};
|
||||
|
||||
static SVCCTL_EvtAckStatus_t serial_svc_event_handler(void* event) {
|
||||
SVCCTL_EvtAckStatus_t ret = SVCCTL_EvtNotAck;
|
||||
hci_event_pckt* event_pckt = (hci_event_pckt*)(((hci_uart_pckt*)event)->data);
|
||||
evt_blecore_aci* blecore_evt = (evt_blecore_aci*)event_pckt->data;
|
||||
aci_gatt_attribute_modified_event_rp0* attribute_modified;
|
||||
if(event_pckt->evt == HCI_VENDOR_SPECIFIC_DEBUG_EVT_CODE) {
|
||||
if(blecore_evt->ecode == ACI_GATT_ATTRIBUTE_MODIFIED_VSEVT_CODE) {
|
||||
attribute_modified = (aci_gatt_attribute_modified_event_rp0*)blecore_evt->data;
|
||||
if(attribute_modified->Attr_Handle == serial_svc->rx_char_handle + 2) {
|
||||
// Descriptor handle
|
||||
ret = SVCCTL_EvtAckFlowEnable;
|
||||
FURI_LOG_D(TAG, "RX descriptor event");
|
||||
} else if(attribute_modified->Attr_Handle == serial_svc->rx_char_handle + 1) {
|
||||
FURI_LOG_D(TAG, "Received %d bytes", attribute_modified->Attr_Data_Length);
|
||||
if(serial_svc->callback) {
|
||||
furi_check(osMutexAcquire(serial_svc->buff_size_mtx, osWaitForever) == osOK);
|
||||
if(attribute_modified->Attr_Data_Length > serial_svc->bytes_ready_to_receive) {
|
||||
FURI_LOG_W(
|
||||
TAG,
|
||||
"Received %d, while was ready to receive %d bytes. Can lead to buffer overflow!",
|
||||
attribute_modified->Attr_Data_Length,
|
||||
serial_svc->bytes_ready_to_receive);
|
||||
}
|
||||
serial_svc->bytes_ready_to_receive -= MIN(
|
||||
serial_svc->bytes_ready_to_receive, attribute_modified->Attr_Data_Length);
|
||||
SerialServiceEvent event = {
|
||||
.event = SerialServiceEventTypeDataReceived,
|
||||
.data = {
|
||||
.buffer = attribute_modified->Attr_Data,
|
||||
.size = attribute_modified->Attr_Data_Length,
|
||||
}};
|
||||
uint32_t buff_free_size = serial_svc->callback(event, serial_svc->context);
|
||||
FURI_LOG_D(TAG, "Available buff size: %d", buff_free_size);
|
||||
furi_check(osMutexRelease(serial_svc->buff_size_mtx) == osOK);
|
||||
}
|
||||
ret = SVCCTL_EvtAckFlowEnable;
|
||||
}
|
||||
} else if(blecore_evt->ecode == ACI_GATT_SERVER_CONFIRMATION_VSEVT_CODE) {
|
||||
FURI_LOG_T(TAG, "Ack received", blecore_evt->ecode);
|
||||
if(serial_svc->callback) {
|
||||
SerialServiceEvent event = {
|
||||
.event = SerialServiceEventTypeDataSent,
|
||||
};
|
||||
serial_svc->callback(event, serial_svc->context);
|
||||
}
|
||||
ret = SVCCTL_EvtAckFlowEnable;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void serial_svc_start() {
|
||||
tBleStatus status;
|
||||
serial_svc = furi_alloc(sizeof(SerialSvc));
|
||||
// Register event handler
|
||||
SVCCTL_RegisterSvcHandler(serial_svc_event_handler);
|
||||
|
||||
// Add service
|
||||
status = aci_gatt_add_service(
|
||||
UUID_TYPE_128, (Service_UUID_t*)service_uuid, PRIMARY_SERVICE, 10, &serial_svc->svc_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to add Serial service: %d", status);
|
||||
}
|
||||
|
||||
// Add RX characteristics
|
||||
status = aci_gatt_add_char(
|
||||
serial_svc->svc_handle,
|
||||
UUID_TYPE_128,
|
||||
(const Char_UUID_t*)char_rx_uuid,
|
||||
SERIAL_SVC_DATA_LEN_MAX,
|
||||
CHAR_PROP_WRITE_WITHOUT_RESP | CHAR_PROP_WRITE | CHAR_PROP_READ,
|
||||
ATTR_PERMISSION_AUTHEN_READ | ATTR_PERMISSION_AUTHEN_WRITE,
|
||||
GATT_NOTIFY_ATTRIBUTE_WRITE,
|
||||
10,
|
||||
CHAR_VALUE_LEN_VARIABLE,
|
||||
&serial_svc->rx_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to add RX characteristic: %d", status);
|
||||
}
|
||||
|
||||
// Add TX characteristic
|
||||
status = aci_gatt_add_char(
|
||||
serial_svc->svc_handle,
|
||||
UUID_TYPE_128,
|
||||
(const Char_UUID_t*)char_tx_uuid,
|
||||
SERIAL_SVC_DATA_LEN_MAX,
|
||||
CHAR_PROP_READ | CHAR_PROP_INDICATE,
|
||||
ATTR_PERMISSION_AUTHEN_READ,
|
||||
GATT_DONT_NOTIFY_EVENTS,
|
||||
10,
|
||||
CHAR_VALUE_LEN_VARIABLE,
|
||||
&serial_svc->tx_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to add TX characteristic: %d", status);
|
||||
}
|
||||
// Add Flow Control characteristic
|
||||
status = aci_gatt_add_char(
|
||||
serial_svc->svc_handle,
|
||||
UUID_TYPE_128,
|
||||
(const Char_UUID_t*)flow_ctrl_uuid,
|
||||
sizeof(uint32_t),
|
||||
CHAR_PROP_READ | CHAR_PROP_NOTIFY,
|
||||
ATTR_PERMISSION_AUTHEN_READ,
|
||||
GATT_DONT_NOTIFY_EVENTS,
|
||||
10,
|
||||
CHAR_VALUE_LEN_CONSTANT,
|
||||
&serial_svc->flow_ctrl_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to add Flow Control characteristic: %d", status);
|
||||
}
|
||||
// Allocate buffer size mutex
|
||||
serial_svc->buff_size_mtx = osMutexNew(NULL);
|
||||
}
|
||||
|
||||
void serial_svc_set_callbacks(
|
||||
uint16_t buff_size,
|
||||
SerialServiceEventCallback callback,
|
||||
void* context) {
|
||||
furi_assert(serial_svc);
|
||||
serial_svc->callback = callback;
|
||||
serial_svc->context = context;
|
||||
serial_svc->buff_size = buff_size;
|
||||
serial_svc->bytes_ready_to_receive = buff_size;
|
||||
uint32_t buff_size_reversed = REVERSE_BYTES_U32(serial_svc->buff_size);
|
||||
aci_gatt_update_char_value(
|
||||
serial_svc->svc_handle,
|
||||
serial_svc->flow_ctrl_char_handle,
|
||||
0,
|
||||
sizeof(uint32_t),
|
||||
(uint8_t*)&buff_size_reversed);
|
||||
}
|
||||
|
||||
void serial_svc_notify_buffer_is_empty() {
|
||||
furi_assert(serial_svc);
|
||||
furi_assert(serial_svc->buff_size_mtx);
|
||||
|
||||
furi_check(osMutexAcquire(serial_svc->buff_size_mtx, osWaitForever) == osOK);
|
||||
if(serial_svc->bytes_ready_to_receive == 0) {
|
||||
FURI_LOG_D(TAG, "Buffer is empty. Notifying client");
|
||||
serial_svc->bytes_ready_to_receive = serial_svc->buff_size;
|
||||
uint32_t buff_size_reversed = REVERSE_BYTES_U32(serial_svc->buff_size);
|
||||
aci_gatt_update_char_value(
|
||||
serial_svc->svc_handle,
|
||||
serial_svc->flow_ctrl_char_handle,
|
||||
0,
|
||||
sizeof(uint32_t),
|
||||
(uint8_t*)&buff_size_reversed);
|
||||
}
|
||||
furi_check(osMutexRelease(serial_svc->buff_size_mtx) == osOK);
|
||||
}
|
||||
|
||||
void serial_svc_stop() {
|
||||
tBleStatus status;
|
||||
if(serial_svc) {
|
||||
// Delete characteristics
|
||||
status = aci_gatt_del_char(serial_svc->svc_handle, serial_svc->tx_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to delete TX characteristic: %d", status);
|
||||
}
|
||||
status = aci_gatt_del_char(serial_svc->svc_handle, serial_svc->rx_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to delete RX characteristic: %d", status);
|
||||
}
|
||||
status = aci_gatt_del_char(serial_svc->svc_handle, serial_svc->flow_ctrl_char_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to delete Flow Control characteristic: %d", status);
|
||||
}
|
||||
// Delete service
|
||||
status = aci_gatt_del_service(serial_svc->svc_handle);
|
||||
if(status) {
|
||||
FURI_LOG_E(TAG, "Failed to delete Serial service: %d", status);
|
||||
}
|
||||
// Delete buffer size mutex
|
||||
osMutexDelete(serial_svc->buff_size_mtx);
|
||||
free(serial_svc);
|
||||
serial_svc = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool serial_svc_is_started() {
|
||||
return serial_svc != NULL;
|
||||
}
|
||||
|
||||
bool serial_svc_update_tx(uint8_t* data, uint16_t data_len) {
|
||||
if(data_len > SERIAL_SVC_DATA_LEN_MAX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for(uint16_t remained = data_len; remained > 0;) {
|
||||
uint8_t value_len = MIN(SERIAL_SVC_CHAR_VALUE_LEN_MAX, remained);
|
||||
uint16_t value_offset = data_len - remained;
|
||||
remained -= value_len;
|
||||
|
||||
tBleStatus result = aci_gatt_update_char_value_ext(
|
||||
0,
|
||||
serial_svc->svc_handle,
|
||||
serial_svc->tx_char_handle,
|
||||
remained ? 0x00 : 0x02,
|
||||
data_len,
|
||||
value_offset,
|
||||
value_len,
|
||||
data + value_offset);
|
||||
|
||||
if(result) {
|
||||
FURI_LOG_E(TAG, "Failed updating TX characteristic: %d", result);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
47
firmware/targets/f6/ble_glue/serial_service.h
Normal file
47
firmware/targets/f6/ble_glue/serial_service.h
Normal file
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define SERIAL_SVC_DATA_LEN_MAX (486)
|
||||
#define SERIAL_SVC_CHAR_VALUE_LEN_MAX (243)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
SerialServiceEventTypeDataReceived,
|
||||
SerialServiceEventTypeDataSent,
|
||||
} SerialServiceEventType;
|
||||
|
||||
typedef struct {
|
||||
uint8_t* buffer;
|
||||
uint16_t size;
|
||||
} SerialServiceData;
|
||||
|
||||
typedef struct {
|
||||
SerialServiceEventType event;
|
||||
SerialServiceData data;
|
||||
} SerialServiceEvent;
|
||||
|
||||
typedef uint16_t (*SerialServiceEventCallback)(SerialServiceEvent event, void* context);
|
||||
|
||||
void serial_svc_start();
|
||||
|
||||
void serial_svc_set_callbacks(
|
||||
uint16_t buff_size,
|
||||
SerialServiceEventCallback callback,
|
||||
void* context);
|
||||
|
||||
void serial_svc_notify_buffer_is_empty();
|
||||
|
||||
void serial_svc_stop();
|
||||
|
||||
bool serial_svc_is_started();
|
||||
|
||||
bool serial_svc_update_tx(uint8_t* data, uint16_t data_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
136
firmware/targets/f6/ble_glue/tl_dbg_conf.h
Normal file
136
firmware/targets/f6/ble_glue/tl_dbg_conf.h
Normal file
@@ -0,0 +1,136 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : App/tl_dbg_conf.h
|
||||
* Description : Debug configuration file for stm32wpan transport layer interface.
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2020 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 */
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __TL_DBG_CONF_H
|
||||
#define __TL_DBG_CONF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* USER CODE BEGIN Tl_Conf */
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "app_conf.h" /* required as some configuration used in dbg_trace.h are set there */
|
||||
#include "dbg_trace.h"
|
||||
#include "hw_if.h"
|
||||
#include <furi_hal.h>
|
||||
|
||||
/**
|
||||
* Enable or Disable traces
|
||||
* The raw data output is the hci binary packet format as specified by the BT specification *
|
||||
*/
|
||||
#define TL_SHCI_CMD_DBG_EN 1 /* Reports System commands sent to CPU2 and the command response */
|
||||
#define TL_SHCI_CMD_DBG_RAW_EN \
|
||||
0 /* Reports raw data System commands sent to CPU2 and the command response */
|
||||
#define TL_SHCI_EVT_DBG_EN 1 /* Reports System Asynchronous Events received from CPU2 */
|
||||
#define TL_SHCI_EVT_DBG_RAW_EN \
|
||||
0 /* Reports raw data System Asynchronous Events received from CPU2 */
|
||||
|
||||
#define TL_HCI_CMD_DBG_EN 1 /* Reports BLE command sent to CPU2 and the command response */
|
||||
#define TL_HCI_CMD_DBG_RAW_EN \
|
||||
0 /* Reports raw data BLE command sent to CPU2 and the command response */
|
||||
#define TL_HCI_EVT_DBG_EN 1 /* Reports BLE Asynchronous Events received from CPU2 */
|
||||
#define TL_HCI_EVT_DBG_RAW_EN 0 /* Reports raw data BLE Asynchronous Events received from CPU2 */
|
||||
|
||||
#define TL_MM_DBG_EN 1 /* Reports the informations of the buffer released to CPU2 */
|
||||
|
||||
/**
|
||||
* System Transport Layer
|
||||
*/
|
||||
#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_CMD_DBG_RAW_EN != 0)
|
||||
#define TL_SHCI_CMD_DBG_RAW(_PDATA_, _SIZE_) furi_hal_console_tx_with_new_line(_PDATA_, _SIZE_)
|
||||
#else
|
||||
#define TL_SHCI_CMD_DBG_RAW(...)
|
||||
#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
|
||||
|
||||
#if(TL_SHCI_EVT_DBG_RAW_EN != 0)
|
||||
#define TL_SHCI_EVT_DBG_RAW(_PDATA_, _SIZE_) furi_hal_console_tx_with_new_line(_PDATA_, _SIZE_)
|
||||
#else
|
||||
#define TL_SHCI_EVT_DBG_RAW(...)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* BLE Transport Layer
|
||||
*/
|
||||
#if(TL_HCI_CMD_DBG_EN != 0)
|
||||
#define TL_HCI_CMD_DBG_MSG PRINT_MESG_DBG
|
||||
#define TL_HCI_CMD_DBG_BUF PRINT_LOG_BUFF_DBG
|
||||
#else
|
||||
#define TL_HCI_CMD_DBG_MSG(...)
|
||||
#define TL_HCI_CMD_DBG_BUF(...)
|
||||
#endif
|
||||
|
||||
#if(TL_HCI_CMD_DBG_RAW_EN != 0)
|
||||
#define TL_HCI_CMD_DBG_RAW(_PDATA_, _SIZE_) furi_hal_console_tx_with_new_line(_PDATA_, _SIZE_)
|
||||
#else
|
||||
#define TL_HCI_CMD_DBG_RAW(...)
|
||||
#endif
|
||||
|
||||
#if(TL_HCI_EVT_DBG_EN != 0)
|
||||
#define TL_HCI_EVT_DBG_MSG PRINT_MESG_DBG
|
||||
#define TL_HCI_EVT_DBG_BUF PRINT_LOG_BUFF_DBG
|
||||
#else
|
||||
#define TL_HCI_EVT_DBG_MSG(...)
|
||||
#define TL_HCI_EVT_DBG_BUF(...)
|
||||
#endif
|
||||
|
||||
#if(TL_HCI_EVT_DBG_RAW_EN != 0)
|
||||
#define TL_HCI_EVT_DBG_RAW(_PDATA_, _SIZE_) furi_hal_console_tx_with_new_line(_PDATA_, _SIZE_)
|
||||
#else
|
||||
#define TL_HCI_EVT_DBG_RAW(...)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Memory Manager - Released buffer tracing
|
||||
*/
|
||||
#if(TL_MM_DBG_EN != 0)
|
||||
#define TL_MM_DBG_MSG PRINT_MESG_DBG
|
||||
#else
|
||||
#define TL_MM_DBG_MSG(...)
|
||||
#endif
|
||||
|
||||
/* USER CODE END Tl_Conf */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*__TL_DBG_CONF_H */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
69
firmware/targets/f6/ble_glue/utilities_conf.h
Normal file
69
firmware/targets/f6/ble_glue/utilities_conf.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : utilities_conf.h
|
||||
* Description : Configuration file for STM32 Utilities.
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2019 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* 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
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef UTILITIES_CONF_H
|
||||
#define UTILITIES_CONF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "cmsis_compiler.h"
|
||||
#include "string.h"
|
||||
|
||||
/******************************************************************************
|
||||
* common
|
||||
******************************************************************************/
|
||||
#define UTILS_ENTER_CRITICAL_SECTION() \
|
||||
uint32_t primask_bit = __get_PRIMASK(); \
|
||||
__disable_irq()
|
||||
|
||||
#define UTILS_EXIT_CRITICAL_SECTION() __set_PRIMASK(primask_bit)
|
||||
|
||||
#define UTILS_MEMSET8(dest, value, size) memset(dest, value, size);
|
||||
|
||||
/******************************************************************************
|
||||
* tiny low power manager
|
||||
* (any macro that does not need to be modified can be removed)
|
||||
******************************************************************************/
|
||||
#define UTIL_LPM_INIT_CRITICAL_SECTION()
|
||||
#define UTIL_LPM_ENTER_CRITICAL_SECTION() UTILS_ENTER_CRITICAL_SECTION()
|
||||
#define UTIL_LPM_EXIT_CRITICAL_SECTION() UTILS_EXIT_CRITICAL_SECTION()
|
||||
|
||||
/******************************************************************************
|
||||
* sequencer
|
||||
* (any macro that does not need to be modified can be removed)
|
||||
******************************************************************************/
|
||||
#define UTIL_SEQ_INIT_CRITICAL_SECTION()
|
||||
#define UTIL_SEQ_ENTER_CRITICAL_SECTION() UTILS_ENTER_CRITICAL_SECTION()
|
||||
#define UTIL_SEQ_EXIT_CRITICAL_SECTION() UTILS_EXIT_CRITICAL_SECTION()
|
||||
#define UTIL_SEQ_CONF_TASK_NBR (32)
|
||||
#define UTIL_SEQ_CONF_PRIO_NBR (2)
|
||||
#define UTIL_SEQ_MEMSET8(dest, value, size) UTILS_MEMSET8(dest, value, size)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*UTILITIES_CONF_H */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
Reference in New Issue
Block a user