Click here for Bluetooth® Low Energy Overview.
1. Introduction
STM32CubeMX tool is a graphical tool that helps you to generate an application targeting the STMicroelectronics MCU of your choice, with initialization code based on the configuration you specify. In the tools interface, you can select the right STMicroelectronics MCU, configure pins, clocks, peripherals, middleware, and it generates code project based on your setup.
This wiki page defines how to generate a Bluetooth® Low Energy (BLE) server application for STM32WBA52CG MCU using STM32CubeMX software.
2. Build a Bluetooth® Low Energy application on STM32WBA with STM32CubeMX
The STM32WBA Nucleo board, flashed with the application generated by STM32CubeMX, can send data to a smartphone (using ST BLE ToolBox application), and receive commands from it through Bluetooth® Low Energy.
System presentation |
---|
This GATT Server application shall be able to expose two services:
- First service exposes two characteristics
- Second service exposes three characteristics
The first service (My_P2P_Server) looks like P2P Server (STM proprietary) with two characteristics:
- Characteristic 1 has Write property
- Characteristic 2 has Notify property
Writing to characteristic 1 toggles blue LED.
Pressing B1 on Nucleo board send data to the phone
Custom Service |
---|
The following steps are recommended to build this application example:
Service and Characteristics configuration are given in the following table:
Service Long Name | My_P2P_Server | |
---|---|---|
Service Short Name | My_P2P | |
UUID Type | 128 bits | |
UUID | 0xFE40 | |
Characteristic Long Name | My_LED_Char | My_Switch_Char |
Characteristic Short Name | LED_C | SWITCH_C |
UUID Type | 128 bits | 128 bits |
UUID | 0xFE41 | 0xFE42 |
Char Properties | Read + Write w/o response | Notify |
Char Permissions | None | None |
Char GATT Events | GATT_NOTIFY_ATTRIBUTE_WRITE | GATT_NOTIFY_ATTRIBUTE_WRITE |
Il va y avoir quelques modification sur ce schema
STM32WBA Application design with STM32CubeMX |
---|
3. Tools
3.1. Software tools
To make and use this project, the needed software tools to complete the application are:
- STM32CubeMX[1] software (from v6.9.0)
- STM32CubeWBA MCU Package[2] (from v1.0.0)
- IDE: STM32CubeIDE[3] or IAR[4]
- Serial Terminal (TeraTerm[5])
- Smartphone application ST BLE ToolBox
3.2. Hardware tools
A STM32WB Nucleo board and a micro-B to Type-A USB cable are also needed.
Hardware presentation |
---|
4. STM32CubeMX initialization for STM32WBA Nucleo Board
4.1. STM32CubeMX initial setup
Open STM32CubeMX and start a new project from the Access to MCU selector button
New Project Menu |
---|
Chose the MCU and then start the new project:
Project Interface |
---|
Start the new project without TrustZone activated
4.2. Pinout and IP configuration
To configure the system, enable all the required system resource and peripherals clicking on A->Z to display all IPs.
Pinout & configuration interface |
---|
BLE mode is reachable once the following system resources and peripherals are turned to enable.
- ADC4 :activate Temperature Sensor Channel
- CRC :Activated
- RAMCFC :Activate SRAM1
- ICACHE :1 way (direct mapped cache)
- RNG :Activated
- RCC : HSE and LSE on Crystal/Ceramic resonator
- RF :Activated
- RTC : Activate clock source
- USART1 : Turn Mode to Asynchronous
- GPDMA1 : Configure channel 0 & 1
- NVIC : Verify NVIC settings
IP list |
---|
4.2.1. ADC4
The 12-bit analog to digital converter has sever (ADC4) has external and two internal (temperature sensor, voltage reference measurement) channels and performs conversions in single-shots or scan modes.
ADC4 configuration |
---|
4.2.2. CRC
The Cyclic Redundancy Check (CRC) is used to verify data transmission or storage integrity.
CRC activation |
---|
4.2.3. RAMCFG
The RAMs ConFiGuration Controller (RAMCFG) configures the features of the internal SRAMs
RAMCFG Activation |
---|
4.2.4. ICACHE
The Instruction CACHE (ICACHE) is introduced on C-AHB code bus of ARM Cortex-M33® processor to improve performance when fetching instruction and data from internal memories.
Configuration of ICACHE is done as follows:
ICACHE Activation |
---|
4.2.5. RNG
The Random Number Generator (RNG) provides full entropy outputs to the application as 32-bit samples.
RNG Activation |
---|
4.2.6. RCC
Reset and Clock Control (RCC) manages the different kind of reset and generates all clocks for the bus and peripherals.
RCC Activation & Setup |
---|
4.2.7. RF
Activate RF
RF Activation |
---|
4.2.8. RTC
Real Time Clock (RTC) provides an automatic wakeup to manage all low-power modes.
RTC Configuration (1/2) |
---|
RTC Configuration (2/2) |
---|
4.2.9. USART1
USART1 is enabled to allow display of traces on a terminal.
USART1 Configuration (1/2) |
---|
USART1 Configuration (2/2) |
---|
4.2.10. GPDMA1
The General Purpose Direct Memory Access (GPDMA) controller is a bus master and system peripheral. The GPDMA is used to perform programmable data transfers between memory-mapped peripherals and/or memories via linked-list, upon the control of an off-loaded CPU.
GPDMA1 Configuration (1/4) |
---|
GPDMA1 Configuration (2/4) |
---|
GPDMA1 Configuration (3/4) |
---|
GPDMA1 Configuration (4/4) |
---|
4.2.11. NVIC
The Nested Vector Interrupt Controller (NVIC) ans the processor core interface are closely coupled, enabling low-latency interrupt processing and efficient processing of late arriving interrupts. All interrupts including the core exceptions are managed by the NVIC.
NVIC Configuration |
---|
4.3. Clock configuration
On Clock Configuration tab, run the automatic clock issue solver (if requested).
This following configuration is defined for initial startup phase. At runtime, clocks will be managed dynamicly by System Clock Manager (SCM) module.
Then:
Clock configuration |
---|
5. BLE GAP/GATT Custom application configuration
Now, we can start configuring and defining the STM32 WPAN.
- Bluetooth® LE Peripheral Custom Template GATT Server Application can be defined:
- On STM32WBA
- With STM32CubeMX (available from Version 6.8.0)
- GAP peripheral : advertising configuration
- GATT server configuration:
- 25 services maximum
- 25 characteristics maximum per service
- ACI commands:
- AN5270: STM32WBx5 Bluetooth® Low Energy (BLE) wireless interface[6].
- AN5270: STM32WBx5 Bluetooth® Low Energy (BLE) wireless interface[6].
5.1. Enable BLE
To configure your application :
STM32_WPAN Mode and Configuration |
---|
5.2. Advertising configuration
Advertising parameters are defined under BLE Advertising tab:
- advertising configuration data are located in app_conf.h and ble_conf.h files
- advertising elements data are located in app_ble.c file
STM32_WPAN Interface: Bluetooth® LE Advertising tab |
---|
Open Advertising Configuration and set the CFG_GAP_DEVICE_NAME to something of your liking, for example MY_APPLI.
This array is defined in app_ble.c file as :
static const char a_GapDeviceName[] = { 'M', 'y', '_', 'A', 'p', 'p', 'l', 'i' }; /* Gap Device Name */
In the generated code these parameters are defined in :
1. app_conf.h file:
#define ADV_TYPE
#define BLE_ADDR_TYPE
#define FILTER
#define ADV_LPINTERVAL_MIN
#define ADV_LPINTERVAL_MAX
2. ble_conf.h file:
#define BLE_CFG_PERIPHERAL
#define BLE_CFG_CENTRAL
STM32_WPAN Interface: Bluetooth® LE Advertising configuration |
---|
In Advertising elements, included in the advertising packet payload :
STM32_WPAN Interface: Advertising elements |
---|
The generated code corresponding to advertising packet elements is located in app_ble.c file.
/**
* Advertising Data
*/
uint8_t a_AdvData[25] =
{
8, AD_TYPE_COMPLETE_LOCAL_NAME, 'p', '2', 'p', 'S', '_', 'X', 'X', /* Complete name */
15, AD_TYPE_MANUFACTURER_SPECIFIC_DATA, 0x30, 0x00, 0x00 /* */, 0x00 /* */, 0x00 /* */, 0x00 /* */, 0x00 /* */, 0x00 /* */, 0x00 /* */, 0x00 /* */, 0x00 /* */, 0x00 /* */, 0x00 /* */, 0x00 /* */,
};
METTRE UN LIEN VERS MANUF / SDK V2
In this case, we will set 2 advertising data elements; local name, and a manufacturer specific field. Make sure to set the fields as you see here:
In our example, we set 2 advertising elements (Advertising packet structure’s length = 25 bytes):
- Complete local name
- Manufacturer specific data
The advertising information is represented by advertising data elements, which are standardized on the Bluetooth SIG.
Manufacturer specific data are updated at runtime (specific function in app_ble.c file)
5.3. Services and characteristics definition
All created services and characteristics are managed in an associated xxx.c file (one file per service, xxx = Service short name defined in SERVICEx panel). Each Service and Characteristic are added in XXX_Init(void) function (XXX = Service short name (capitalized) defined in SERVICEx panel) using :
- aci_gatt_add_service(…) for services
- aci_gatt_add_char(…) for characteristics
5.3.1. BLE Applications and Services
To start the definition of the Bluetooth LE application :
Bluetooth® LE Applications and Services |
---|
5.3.2. Services definition
Each created Service is defined in a dedicated tab (SERVICE 1 to 25) :
- Up to 25 Characteristics per Service
- UUID type can be defined as 16 or 128 bits (full or reduced)
- UUID definition
- Type value is Primary or Secondary Service
Once the number of service has been defined, in our example we defined one service with two characteristics, update the service information.
Service Definition |
---|
5.3.3. Characteristics definition
For each characteristic the following parameters must be defined
- General
- Properties
- Permissions
- GATT events
Our example defines 2 characteristics:
Characteristic 1 | Characteristic 2 | ||||
---|---|---|---|---|---|
UUID type | 128 bits UUID (0x02) | 128 bits UUID (0x02) | |||
UUID 128 Input type | Reduced | Reduced | |||
UUID | FE 41 | FE 42 | |||
Characteristic long name | My_LED_Char | My_Switch_Char | |||
Characteristic Short Name | LED_C | SWITCH_C | |||
Value length | 2 | 2 | |||
Length characteristic | Variable | Variable | |||
Encryption key size | 0x10 | 0x10 | |||
Char Properties | READ | WRITE_WITHOUT_RESP | NOTIFY | ||
GATT events | GATT_NOTIFY_ATTRIBUTE_WRITE | GATT_NOTIFY_ATTRIBUTE_WRITE |
Defined as follows:
SERVICE1 characteristics definition |
---|
5.4. Application Configuration
All the Application Configuration topics are reachable when :
Application Configuration (1/12) |
---|
5.4.1. Project IP's Configuration
To display Application configuration recommendations:
Application Configuration (2/12) |
---|
5.4.2. Application Parameter
Pairing is done to support secure connection method.
All parameters defined in this chapter are located in app_conf.h file.
Application Configuration (3/12) |
---|
5.4.3. BLE Stack
Application Configuration (4/12) |
---|
5.4.4. Low Power
Application Configuration (5/12) |
---|
5.4.5. Traces
Application Configuration (6/12) |
---|
5.4.6. Log level
Application Configuration (7/12) |
---|
5.4.7. NVM
Application Configuration (8/12) |
---|
5.4.8. RT GPIO debug
Application Configuration (9/12) |
---|
5.4.9. HW Radio
Application Configuration (10/12) |
---|
5.4.10. HW_RNG
Application Configuration (11/12) |
---|
5.4.11. Memory manager
Application Configuration (12/12) |
---|
5.5. Platefrom Settings
BSP settings :
Platform Settings |
---|
6. Project Configuration
All the project configuration is done on the Project Manager pane within three sections:
- Project
- Code generator
- Advanced Settings
Project Configuration (1/4) |
---|
Management of files, packages and embedded software packs are done from Code Generator panel.
Project Configuration (2/4) |
---|
Project Configuration (3/4) |
---|
In Advanced Settings panel:
- Do Not Generate Function Call shall be unticked for all IP’s associated to STM32WPAN configurationexcepted for CRC.
- Visibility Static shall be unticked for all IP’s associated to STM32WPAN configuration excepted for GPDMA (when activated), ADC, and SystemPower_Config.
- Generate code shall be ticked for all functions
Then turn UART to enable in Register Callback panel:
Project Configuration (4/4) |
---|
7. P2P Server notifications and writes management
In order to use P2P Server Notification and Write characteristics, several points have to be configured:
- User Button and the related Interrupt, to Notify the P2P Client
- Blue LED, to receive a P2P Client write operation
- Custom application code to manage B1 and write operation on P2P Server service
STM32WBA Nucleo board |
---|
7.1. User button and LED pinout
In the Nucleo board, LED pinout is:
- Blue LED : PB4
- Red LED: PB8
- Green LED: PA9
Switch (user button) pinout is:
- B1: PC13
- B2: PB6
- B3: PB7
When used:
- Switch pins are declared as GPIO_EXTIx (x = pin number)
- LED pins are declared as GPIO_OUTPUT
7.2. LEDs setup
For the blue LED setup, go to Pinout and Configuration window, then :
Blue LED Pinout |
---|
For the red LED :
Red LED Pinout |
---|
For the green LED :
GreenLED Pinout |
---|
Once the three Leds (Blue, Green, Red) have been added, their configuration can be done :
LEDs Configuration |
---|
7.3. Buttons setup
For B1 setup go to Pinout and Configuration window, then :
B1 Pinout |
---|
For B2 setup :
B2 Pinout |
---|
For B3 setup :
B3 Pinout |
---|
Once the three Buttons (B1, B2, B3) have been added, their configuration can be done:
Buttons Configuration |
---|
7.4. NVIC Configuration
Once buttons have been defined, configure NVIC:
NVIC Configuration |
---|
8. Code Generation
Once configuration is done in STM32CubeMX:
Code Generation |
---|
9. Code modification: User sections
Once your Buttons and LEDs GPIOs are correctly setup, generate your project by following the steps described in Code Generation chapter.
The generated source code contains several sections called User Sections where users can add custom application code parts.
These sections are not erased/modified at project regeneration from STM32CubeMX.
In order to manage notify and write operation on P2P Server service, some code parts have to be added in User Sections of the following files and their respective header files:
Files to update |
---|
- In app_conf.h:
From app_conf.h, define the tasks for buttons, notifications and adv by adding code in CFG_Task_Id_t User Code Section:
typedef enum
{
CFG_TASK_HCI_ASYNCH_EVT_ID,
CFG_TASK_LINK_LAYER,
CFG_TASK_LINK_LAYER_TEMP_MEAS,
CFG_TASK_BLE_HOST,
CFG_TASK_BPKA,
CFG_TASK_HW_RNG,
CFG_TASK_AMM_BCKGND,
CFG_TASK_FLASH_MANAGER_BCKGND,
CFG_TASK_BLE_TIMER_BCKGND,
/* USER CODE BEGIN CFG_Task_Id_t */
TASK_BUTTON_1,
TASK_BUTTON_2,
TASK_BUTTON_3,
CFG_TASK_ADV_CANCEL_ID,
CFG_TASK_SEND_NOTIF_ID,
/* USER CODE END CFG_Task_Id_t */
CFG_TASK_NBR /* Shall be LAST in the list */
} CFG_Task_Id_t;
Update also USER CODE Defines to support LED, Button and Debug :
/* USER CODE BEGIN Defines */
/**
* User interaction
* When CFG_LED_SUPPORTED is set, LEDS are activated if requested
* When CFG_BUTTON_SUPPORTED is set, the push button are activated if requested
* When CFG_DBG_SUPPORTED is set, the debugger is activated
*/
#define CFG_LED_SUPPORTED (1)
#define CFG_BUTTON_SUPPORTED (1)
#define CFG_DBG_SUPPORTED (1)
/**
* If CFG_FULL_LOW_POWER is requested, make sure LED and debugger are disabled
*/
#if (CFG_FULL_LOW_POWER == 1)
#undef CFG_LED_SUPPORTED
#define CFG_LED_SUPPORTED (0)
#undef CFG_DBG_SUPPORTED
#define CFG_DBG_SUPPORTED (0)
#endif /* CFG_FULL_LOW_POWER */
/**
* Timeout for advertising
*/
#define ADV_TIMEOUT_MS (60*1000) /**< 60s */
/* USER CODE END Defines */
- In main.c:
/* USER CODE BEGIN ICACHE_Init 1 */
/* No retention for ICACHE in stop mode */
LL_PWR_SetICacheRAMStopRetention(LL_PWR_ICACHERAM_STOP_NO_RETENTION);
/* USER CODE END ICACHE_Init 1 */
/* USER CODE BEGIN RNG_Init 0 */
memset(&hrng, 0, sizeof(hrng));
/* USER CODE END RNG_Init 0 */
/* USER CODE BEGIN RNG_Init 2 */
/* Disable RNG peripheral and its RCC clock */
HW_RNG_Disable( );
/* USER CODE END RNG_Init 2 */
/* USER CODE BEGIN MX_GPIO_Init_2 */
#if (CFG_DBG_SUPPORTED == 0)
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Pin = GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_13;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_4;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
#endif
/* USER CODE END MX_GPIO_Init_2 */
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
Error_Handler();
/* USER CODE END 6 */
- In stm32wbaxx_it.c:
/* USER CODE BEGIN Includes */
#include "stm32wbaxx_nucleo.h"
/* USER CODE END Includes */
/* USER CODE BEGIN EXTI6_IRQn 1 */
BSP_PB_IRQHandler(B2);
/* USER CODE END EXTI6_IRQn 1 */
/* USER CODE BEGIN EXTI7_IRQn 1 */
BSP_PB_IRQHandler(B3);
/* USER CODE END EXTI7_IRQn 1 */
/* USER CODE BEGIN EXTI13_IRQn 1 */
BSP_PB_IRQHandler(B1);
/* USER CODE END EXTI13_IRQn 1 */
- In app_entry.c:
/* USER CODE BEGIN Includes */
#include "stm32wbaxx_nucleo.h"
/* USER CODE END Includes */
/* USER CODE BEGIN PFP */
#if (CFG_LED_SUPPORTED == 1)
static void Led_Init(void);
#endif
#if (CFG_BUTTON_SUPPORTED == 1)
static void Button_Init(void);
#endif
/* USER CODE END PFP */
/* USER CODE BEGIN APPE_Init_1 */
#if (CFG_LED_SUPPORTED == 1)
Led_Init();
#endif
#if (CFG_BUTTON_SUPPORTED == 1)
Button_Init();
#endif
/* USER CODE END APPE_Init_1 */
/* USER CODE BEGIN APPE_Init_2 */
#if (CFG_BUTTON_SUPPORTED == 1)
/* Register Button Tasks */
UTIL_SEQ_RegTask(1U << CFG_TASK_PB1_BUTTON_PUSHED_ID, UTIL_SEQ_RFU, APP_BLE_Key_Button1_Action);
UTIL_SEQ_RegTask(1U << CFG_TASK_PB2_BUTTON_PUSHED_ID, UTIL_SEQ_RFU, APP_BLE_Key_Button2_Action);
UTIL_SEQ_RegTask(1U << CFG_TASK_PB3_BUTTON_PUSHED_ID, UTIL_SEQ_RFU, APP_BLE_Key_Button3_Action);
#endif
/* USER CODE END APPE_Init_2 */
/* USER CODE BEGIN FD_LOCAL_FUNCTIONS */
#if (CFG_LED_SUPPORTED == 1)
static void Led_Init( void )
{
/* Leds Initialization */
BSP_LED_Init(LED_BLUE);
BSP_LED_Init(LED_GREEN);
BSP_LED_Init(LED_RED);
BSP_LED_On(LED_GREEN);
return;
}
#endif
#if (CFG_BUTTON_SUPPORTED == 1)
static void Button_Init( void )
{
/* Button Initialization */
BSP_PB_Init(B1, BUTTON_MODE_EXTI);
BSP_PB_Init(B2, BUTTON_MODE_EXTI);
BSP_PB_Init(B3, BUTTON_MODE_EXTI);
return;
}
#endif
/* USER CODE END FD_LOCAL_FUNCTIONS */
/* USER CODE BEGIN FD_WRAP_FUNCTIONS */
void BSP_PB_Callback(Button_TypeDef Button)
{
switch (Button)
{
case B1:
UTIL_SEQ_SetTask(1U << CFG_TASK_PB1_BUTTON_PUSHED_ID, CFG_SEQ_PRIO_0);
break;
case B2:
UTIL_SEQ_SetTask(1U << CFG_TASK_PB2_BUTTON_PUSHED_ID, CFG_SEQ_PRIO_0);
break;
case B3:
UTIL_SEQ_SetTask(1U << CFG_TASK_PB3_BUTTON_PUSHED_ID, CFG_SEQ_PRIO_0);
break;
default:
break;
}
return;
}
void HAL_GPIO_EXTI_Rising_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == B1_PIN)
{
BSP_PB_Callback(B1);
}
if (GPIO_Pin == B2_PIN)
{
BSP_PB_Callback(B2);
}
if (GPIO_Pin == B3_PIN)
{
BSP_PB_Callback(B3);
}
return;
}
void HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin)
{
HAL_GPIO_EXTI_Rising_Callback(GPIO_Pin);
}
/* USER CODE END FD_WRAP_FUNCTIONS */
- In app_ble.h:
From app_ble.h, declare button action functions, in EF User Code Section:
/* USER CODE BEGIN EF */
void APP_BLE_Key_Button1_Action(void);
void APP_BLE_Key_Button2_Action(void);
void APP_BLE_Key_Button3_Action(void);
/* USER CODE END EF */
- In app_ble.c:
/* USER CODE BEGIN Includes */
#include "stm32wbaxx_nucleo.h"
/* USER CODE END Includes */
/* USER CODE BEGIN PTD_1*/
/* Advertising timeout timerID*/
UTIL_TIMER_Object_t Advertising_mgr_timer_Id;
/* Led Timeout timerID */
UTIL_TIMER_Object_t SwitchOffGPIO_timer_Id;
uint8_t connIntervalFlag;
/* USER CODE END PTD_1 */
/* USER CODE BEGIN PD */
#define LED_ON_TIMEOUT (5)
/* USER CODE END PD */
/* USER CODE BEGIN PFP */
static void Adv_Cancel_Req(void *arg);
static void Adv_Cancel(void);
static void Switch_OFF_GPIO(void *arg);
static void fill_advData(uint8_t *p_adv_data, uint8_t tab_size, const uint8_t*p_bd_addr);
/* USER CODE END PFP */
/* USER CODE BEGIN APP_BLE_Init_1 */
tBleStatus ret = BLE_STATUS_INVALID_PARAMS;
/* USER CODE END APP_BLE_Init_1 */
/* USER CODE BEGIN APP_BLE_Init_4 */
UTIL_SEQ_RegTask(1<<CFG_TASK_ADV_CANCEL_ID, UTIL_SEQ_RFU, Adv_Cancel);
/* Create timer to handle the Advertising Stop */
UTIL_TIMER_Create(&(bleAppContext.Advertising_mgr_timer_Id),
0,
(UTIL_TIMER_Mode_t)hw_ts_SingleShot,
&Adv_Cancel_Req,
0);
/* Create timer to handle the Led Switch OFF */
UTIL_TIMER_Create(&(bleAppContext.SwitchOffGPIO_timer_Id),
0,
(UTIL_TIMER_Mode_t)hw_ts_SingleShot,
&Switch_OFF_GPIO,
0);
/* USER CODE END APP_BLE_Init_4 */
/* USER CODE BEGIN APP_BLE_Init_3 */
ret = aci_hal_set_radio_activity_mask(0x0006);
if (ret != BLE_STATUS_SUCCESS)
{
APP_DBG_MSG(" Fail : aci_hal_set_radio_activity_mask command, result: 0x%2X\n", ret);
}
else
{
APP_DBG_MSG(" Success: aci_hal_set_radio_activity_mask command\n\r");
}
/* Start to Advertise to accept a connection */
APP_BLE_Procedure_Gap_Peripheral(PROC_GAP_PERIPH_ADVERTISE_START_FAST);
/* Start a timer to stop advertising after a while */
UTIL_TIMER_StartWithPeriod(&bleAppContext.Advertising_mgr_timer_Id, INITIAL_ADV_TIMEOUT);
/* USER CODE END APP_BLE_Init_3 */
/* USER CODE BEGIN APP_BLE_Init_2 */
bleAppContext.connIntervalFlag = 0;
/* USER CODE END APP_BLE_Init_2 */
/* USER CODE BEGIN EVT_DISCONN_COMPLETE */
APP_BLE_Procedure_Gap_Peripheral(PROC_GAP_PERIPH_ADVERTISE_START_FAST);
UTIL_TIMER_StartWithPeriod(&bleAppContext.Advertising_mgr_timer_Id, INITIAL_ADV_TIMEOUT);
/* USER CODE END EVT_DISCONN_COMPLETE */
/* USER CODE BEGIN HCI_EVT_LE_ENHANCED_CONN_COMPLETE */
/* The connection is done, there is no need anymore to schedule the LP ADV */
UTIL_TIMER_Stop(&(bleAppContext.Advertising_mgr_timer_Id));
/* USER CODE END HCI_EVT_LE_ENHANCED_CONN_COMPLETE */
/* USER CODE BEGIN HCI_EVT_LE_CONN_COMPLETE */
/* The connection is done, there is no need anymore to schedule the LP ADV */
UTIL_TIMER_Stop(&(bleAppContext.Advertising_mgr_timer_Id));
/* USER CODE END HCI_EVT_LE_CONN_COMPLETE */
/* USER CODE BEGIN RADIO_ACTIVITY_EVENT*/
BSP_LED_On(LED_GREEN);
UTIL_TIMER_StartWithPeriod(&bleAppContext.SwitchOffGPIO_timer_Id, LED_ON_TIMEOUT);
/* USER CODE END RADIO_ACTIVITY_EVENT*/
/* USER CODE BEGIN CONN_PARAM_UPDATE */
if (bleAppContext.connIntervalFlag != 0)
{
bleAppContext.connIntervalFlag = 0;
paramA = CONN_INT_MS(50);
paramB = CONN_INT_MS(50);
}
else
{
bleAppContext.connIntervalFlag = 1;
paramA = CONN_INT_MS(1000);
paramB = CONN_INT_MS(1000);
}
/* USER CODE END CONN_PARAM_UPDATE */
/* USER CODE BEGIN FD*/
void APP_BLE_Key_Button1_Action(void)
{
if (bleAppContext.Device_Connection_Status == APP_BLE_IDLE)
{
/* Relaunch advertising */
APP_BLE_Procedure_Gap_Peripheral(PROC_GAP_PERIPH_ADVERTISE_START_FAST);
UTIL_TIMER_StartWithPeriod(&bleAppContext.Advertising_mgr_timer_Id, INITIAL_ADV_TIMEOUT);
}
else
{
UTIL_SEQ_SetTask( 1<<CFG_TASK_SEND_NOTIF_ID, CFG_SCH_PRIO_0);
}
return;
}
void APP_BLE_Key_Button2_Action(void)
{
tBleStatus ret = BLE_STATUS_INVALID_PARAMS;
if (bleAppContext.Device_Connection_Status != APP_BLE_CONNECTED_SERVER)
{
ret = aci_gap_clear_security_db();
if (ret != BLE_STATUS_SUCCESS)
{
APP_DBG_MSG("==>> aci_gap_clear_security_db - Fail, result: 0x%02X\n", ret);
}
else
{
APP_DBG_MSG("==>> aci_gap_clear_security_db - Success\n");
}
}
else
{
/* Launch advertising for multi connection */
APP_BLE_Procedure_Gap_Peripheral(PROC_GAP_PERIPH_ADVERTISE_START_FAST);
UTIL_TIMER_StartWithPeriod(&bleAppContext.Advertising_mgr_timer_Id, INITIAL_ADV_TIMEOUT);
}
return;
}
void APP_BLE_Key_Button3_Action(void)
{
if (bleAppContext.Device_Connection_Status != APP_BLE_CONNECTED_SERVER)
{
}
else
{
APP_BLE_Procedure_Gap_Peripheral(PROC_GAP_PERIPH_CONN_PARAM_UPDATE);
}
return;
}
/* USER CODE END FD*/
/* USER CODE BEGIN Ble_Hci_Gap_Gatt_Init_1*/
fill_advData(&a_AdvData[0], sizeof(a_AdvData), p_bd_addr);
/* USER CODE END Ble_Hci_Gap_Gatt_Init_1*/
/* USER CODE BEGIN FD_LOCAL_FUNCTION */
static void Adv_Cancel_Req(void *arg)
{
UTIL_SEQ_SetTask(1 << CFG_TASK_ADV_CANCEL_ID, CFG_SCH_PRIO_0);
return;
}
static void Switch_OFF_GPIO(void *arg)
{
BSP_LED_Off(LED_GREEN);
return;
}
static void Adv_Cancel(void)
{
BSP_LED_Off(LED_GREEN);
APP_BLE_Procedure_Gap_Peripheral(PROC_GAP_PERIPH_ADVERTISE_STOP);
bleAppContext.Device_Connection_Status = APP_BLE_IDLE;
return;
}
static void fill_advData(uint8_t *p_adv_data, uint8_t tab_size, const uint8_t* p_bd_addr)
{
uint16_t i =0;
uint8_t bd_addr_1, bd_addr_0;
uint8_t ad_length, ad_type;
while(i < tab_size)
{
ad_length = p_adv_data[i];
ad_type = p_adv_data[i + 1];
switch (ad_type)
{
case AD_TYPE_FLAGS:
break;
case AD_TYPE_TX_POWER_LEVEL:
break;
case AD_TYPE_COMPLETE_LOCAL_NAME:
{
if((p_adv_data[i + ad_length] == 'X') && (p_adv_data[i + ad_length - 1] == 'X'))
{
bd_addr_1 = ((p_bd_addr[0] & 0xF0)>>4);
bd_addr_0 = (p_bd_addr[0] & 0xF);
/* Convert hex value into ascii */
if(bd_addr_1 > 0x09)
{
p_adv_data[i + ad_length - 1] = bd_addr_1 + '7';
}
else
{
p_adv_data[i + ad_length - 1] = bd_addr_1 + '0';
}
if(bd_addr_0 > 0x09)
{
p_adv_data[i + ad_length] = bd_addr_0 + '7';
}
else
{
p_adv_data[i + ad_length] = bd_addr_0 + '0';
}
}
break;
}
case AD_TYPE_MANUFACTURER_SPECIFIC_DATA:
{
p_adv_data[i+2] = 0x30;
p_adv_data[i+3] = 0x00;
p_adv_data[i+4] = 0x02; /* blueST SDK version */
p_adv_data[i+5] = 0x8B; /* Board ID */
p_adv_data[i+6] = 0x83; /* FW ID */
p_adv_data[i+7] = 0x00; /* FW data 1 */
p_adv_data[i+8] = 0x00; /* FW data 2 */
p_adv_data[i+9] = 0x00; /* FW data 3 */
p_adv_data[i+10] = p_bd_addr[5]; /* MSB BD address */
p_adv_data[i+11] = p_bd_addr[4];
p_adv_data[i+12] = p_bd_addr[3];
p_adv_data[i+13] = p_bd_addr[2];
p_adv_data[i+14] = p_bd_addr[1];
p_adv_data[i+15] = p_bd_addr[0]; /* LSB BD address */
break;
}
default:
break;
}
i += ad_length + 1; /* increment the iterator to go on next element*/
}
}
/* USER CODE END FD_LOCAL_FUNCTION */
- In p2p_server.c:
/* USER CODE BEGIN Service1_Char_1_ACI_GATT_ATTRIBUTE_MODIFIED_VSEVT_CODE */
APP_DBG_MSG("-- GATT : LED CONFIGURATION RECEIVED\n");
notification.DataTransfered.Length = p_attribute_modified->Attr_Data_Length;
notification.DataTransfered.p_Payload = p_attribute_modified->Attr_Data;
/* USER CODE END Service1_Char_1_ACI_GATT_ATTRIBUTE_MODIFIED_VSEVT_CODE */
/* USER CODE BEGIN BLECORE_EVT */
/* Manage ACI_GATT_INDICATION_VSEVT_CODE occurring on Android 12 */
case ACI_GATT_INDICATION_VSEVT_CODE:
{
tBleStatus status = BLE_STATUS_FAILED;
aci_gatt_indication_event_rp0 *pr = (void*)p_blecore_evt->data;
status = aci_gatt_confirm_indication(pr->Connection_Handle);
if (status != BLE_STATUS_SUCCESS)
{
APP_DBG_MSG(" Fail : aci_gatt_confirm_indication command, result: 0x%x \n", status);
}
else
{
APP_DBG_MSG(" Success: aci_gatt_confirm_indication command\n");
}
}
break; /* end ACI_GATT_NOTIFICATION_VSEVT_CODE */
/* USER CODE END BLECORE_EVT */
- In p2p_server_app.c:
/* USER CODE BEGIN Includes */
#include "stm32wbaxx_nucleo.h"
/* USER CODE END Includes */
/* USER CODE BEGIN PTD */
typedef struct{
uint8_t Device_Led_Selection;
uint8_t Led1;
}P2P_LedCharValue_t;
typedef struct{
uint8_t Device_Button_Selection;
uint8_t ButtonStatus;
}P2P_ButtonCharValue_t;
/* USER CODE END PTD */
/* USER CODE BEGIN Service1_APP_Context_t */
P2P_LedCharValue_t LedControl;
P2P_ButtonCharValue_t ButtonControl;
/* USER CODE END Service1_APP_Context_t */
/* USER CODE BEGIN PFP */
static void P2P_SERVER_APP_LED_BUTTON_context_Init(void);
/* USER CODE END PFP */
/* USER CODE BEGIN Service1Char1_WRITE_NO_RESP_EVT */
if(p_Notification->DataTransfered.p_Payload[1] == 0x01)
{
BSP_LED_On(LED_BLUE);
APP_DBG_MSG("-- P2P APPLICATION SERVER : LED1 ON\n");
P2P_SERVER_APP_Context.LedControl.Led1 = 0x01; /* LED1 ON */
}
if(p_Notification->DataTransfered.p_Payload[1] == 0x00)
{
BSP_LED_Off(LED_BLUE);
APP_DBG_MSG("-- P2P APPLICATION SERVER : LED1 OFF\n");
P2P_SERVER_APP_Context.LedControl.Led1 = 0x00; /* LED1 OFF */
}
/* USER CODE END Service1Char1_WRITE_NO_RESP_EVT */
/* USER CODE BEGIN Service1Char2_NOTIFY_ENABLED_EVT */
P2P_SERVER_APP_Context.Switch_c_Notification_Status = Switch_c_NOTIFICATION_ON;
APP_DBG_MSG("-- P2P APPLICATION SERVER : NOTIFICATION ENABLED\n");
APP_DBG_MSG(" \n\r");
/* USER CODE END Service1Char2_NOTIFY_ENABLED_EVT */
/* USER CODE BEGIN Service1Char2_NOTIFY_DISABLED_EVT */
P2P_SERVER_APP_Context.Switch_c_Notification_Status = Switch_c_NOTIFICATION_OFF;
APP_DBG_MSG("-- P2P APPLICATION SERVER : NOTIFICATION DISABLED\n");
APP_DBG_MSG(" \n\r");
/* USER CODE END Service1Char2_NOTIFY_DISABLED_EVT */
/* USER CODE BEGIN Service1_APP_DISCON_HANDLE_EVT */
P2P_SERVER_APP_LED_BUTTON_context_Init();
/* USER CODE END Service1_APP_DISCON_HANDLE_EVT */
/* USER CODE BEGIN Service1_APP_Init */
UTIL_SEQ_RegTask( 1U << CFG_TASK_SEND_NOTIF_ID, UTIL_SEQ_RFU, P2P_SERVER_Switch_c_SendNotification);
/**
* Initialize LedButton Service
*/
P2P_SERVER_APP_Context.Switch_c_Notification_Status= Switch_c_NOTIFICATION_OFF;
P2P_SERVER_APP_LED_BUTTON_context_Init();
/* USER CODE END Service1_APP_Init */
/* USER CODE BEGIN FD */
void P2P_SERVER_APP_LED_BUTTON_context_Init(void)
{
BSP_LED_Off(LED_BLUE);
P2P_SERVER_APP_Context.LedControl.Device_Led_Selection=0x01; /* Device1 */
P2P_SERVER_APP_Context.LedControl.Led1=0x00; /* led OFF */
P2P_SERVER_APP_Context.ButtonControl.Device_Button_Selection=0x01;/* Device1 */
P2P_SERVER_APP_Context.ButtonControl.ButtonStatus=0x00;
return;
}
/* USER CODE END FD */
/* USER CODE BEGIN Service1Char2_NS_1*/
if(P2P_SERVER_APP_Context.ButtonControl.ButtonStatus == 0x00)
{
P2P_SERVER_APP_Context.ButtonControl.ButtonStatus = 0x01;
}
else
{
P2P_SERVER_APP_Context.ButtonControl.ButtonStatus = 0x00;
}
a_P2P_SERVER_UpdateCharData[0] = 0x01; /* Device Led selection */
a_P2P_SERVER_UpdateCharData[1] = P2P_SERVER_APP_Context.ButtonControl.ButtonStatus;
/* Update notification data length */
p2p_server_notification_data.Length = (p2p_server_notification_data.Length) + 2;
if(P2P_SERVER_APP_Context.Switch_c_Notification_Status == Switch_c_NOTIFICATION_ON)
{
APP_DBG_MSG("-- P2P APPLICATION SERVER : INFORM CLIENT BUTTON 1 PUSHED\n");
notification_on_off = Switch_c_NOTIFICATION_ON;
}
else
{
APP_DBG_MSG("-- P2P APPLICATION SERVER : CAN'T INFORM CLIENT - NOTIFICATION DISABLED\n");
}
/* USER CODE END Service1Char2_NS_1*/
10. Inserting external files
To complete the creation of our p2pServer project we will now add the following external BSP files:
- stm32wbaxx_nucleo.c
- stm32wbaxx_nucleo.h
You can download all BSP STM32WBAXX-NUCLEO Component here.
Those file provide a set of firmware functions to manage the LEDs and push buttons available on the STM32WBAxx-Nucleo kit.
To add external files, we recommend using the .extSettings file. However it is also possible to add them manually as described later.
10.1. Adding files using .extSettings
The .extsettings file allows you to add additional settings witch can be used when external tools call STM32CubeMX to generate the project and require specific project settings.
.extSettings file |
---|
Your .extSettings file should be constituted as followed:
[ProjectFiles]
HeaderPath=..\Core\Inc\
[Others]
[Groups]
Drivers/BSP/STM32WBAxx_Nucleo = ../Core/Src/stm32wbaxx_nucleo.c;
In our case, the HearderPath indicate where stm32wbaxx_nucleo.h file is in your project. Then under Groups you need to specify where you want the code file to appear in your workspace, and where it is stored.
Now you can click Generate again in STM32CubeMX.
Here is how your space should look like now:
10.2. Adding files manually
The steps below were made with the IAR IDE.
To include manually the BSP code file :
Adding stm32wbaxx_nucleo.c |
---|
To specify manually the header path :
Adding stm32wbaxx_nucleo.h (1/4) |
---|
Adding stm32wbaxx_nucleo.h (2/4) |
---|
Adding stm32wbaxx_nucleo.h (3/4) |
---|
Adding stm32wbaxx_nucleo.h (4/4) |
---|
You have just finished creating a p2pServer application with STM32CubeMX starting from the STM32WBA52CGU6 ship.
You can find more information about Peer 2 Peer Applications on: Connectivity:STM32WBA_Peer_To_Peer
11. References