STM32WBA Bluetooth® LE - STM32CubeMX Application Conception

Click here for Bluetooth® Low Energy Overview.
Click here for an Introduction to Bluetooth® Low Energy with STM32.

1. Introduction

STM32CubeMX tool is a graphical tool that helps you 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 your STMicroelectronics MCU, configure pins, clocks, peripherals, and middleware, and it generates the code project based on your setup.

This wiki page demonstrates how to generate a Bluetooth® Low Energy server application for an STM32WBA52CG MCU using STM32CubeMX software.

2. Build a Bluetooth® Low Energy application on STM32WBA with STM32CubeMX

The STM32WBA Nucleo board, programmed with the application generated by STM32CubeMX, can send data to a smartphone (using the ST BLE ToolBox application), and receive commands from it through Bluetooth® Low Energy.

System presentation
Connectivity WBA CMX System Presentation


A Generic Attribute (GATT) server application will be able to expose some user services. Note that the Generic Access Profile (GAP) and GATT services are automatically added to the list of user services. For our peer-to-peer (P2P) server application we use two user services:

  • The first service exposes two characteristics.
  • The second service exposes three characteristics.

The first service (My_P2P_Server) looks like a P2P server (STM proprietary) with two characteristics:

  • Characteristic 1 has Write property.
  • Characteristic 2 has Notify property.

Writing to characteristic 1 toggles the blue LED.
Pressing Button 1 on the Nucleo board sends data to the phone.

Custom Service
Connectivity WBA CMX Custom Service


The following steps are recommended to build this application example:

Step by step 1 logo.png

Step 1: STM32CubeMX initialization for STM32WBA Nucleo board
Initialize an STM32CubeMX project targeting the STM32WBA52GG platform.

Step by step 2 logo.png

Step 2: STM32WBA IP configuration
Enable the required system resources and peripherals to make a Bluetooth® Low Energy application work.

Step by step 3 logo.png

Step 3: Clock configuration
Set up the project clocks.

Step by step 4 logo.png
Step 4: Project setup
Define the project settings for C code generation, such as project name, IDE, firmware location.
Step by step 5 logo.png
Step 5: Bluetooth® Low Energy GAP/GATT custom application configuration
Define the Bluetooth® Low Energy application configuration, such as advertising parameters, services and characteristics.


Service and characteristic configurations 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
Info white.png Information
Only 2 bytes are defined by the user for the 16- or 128-bit UUID.

3. Tools

3.1. Software tools

To make and use this application project, you need the following software tools:

  • STM32CubeMX[1] software (v6.9.0 or up)
  • STM32CubeWBA MCU package[2] (v1.1.0 or up)
  • IDE: STM32CubeIDE[3] or IAR[4]
  • Serial Terminal (TeraTerm[5])
  • Smartphone application ST BLE ToolBox

3.2. Hardware tools

You also need an STM32WB Nucleo board and a micro-B to Type-A USB cable.

Hardware presentation
Connectivity WBA CMX Hardware Presentation.jpg


4. STM32CubeMX initialization for STM32WBA Nucleo board

With the STM32CubeMX software tool, it is possible to start your project at different levels.
Directly from the chip, or from boards with the hardware support already configured. Or even directly from an embedded application developed by STMicroelectronics.
In this example, we will start with the STM32WBA52CG chip to detail all the configuration steps to enable Bluetooth® Low Energy and create an application. In this case, it will be a P2P server application.

STM32WBA application design with STM32CubeMX for a P2P server application
Connectivity WBA CMX STM32CubeMX Application Design Drawing.jpg


4.1. STM32CubeMX initial setup

Open STM32CubeMX and start a new project by clicking on the Access to MCU selector button

New Project menu
Connectivity wiki photo 03.png


Select the correct MCU and start the new project:

puce1.png
In the MCU/MPU Selector tab, open the Series menu under PRODUCT INFO.
puce2.png
Check STM32WBA.
puce3.png
Select the STM32WBA52CGU6 part number.
puce4.png
Click Start project.
Project Interface
Connectivity WBA CMX Project Interface.jpg


Start the new project without activating TrustZone:

Connectivity WBA CMX Trust Zone Activation.jpg

4.2. Pinout and IP configuration

To configure the system, enable all the required system resources and peripherals by clicking on the A->Z tab to display all IPs.

Pinout & configuration interface
Connectivity WBA CMX pinout Config Interface.jpg


Bluetooth® Low Energy mode is reachable once the following system resources and peripherals are set to "enabled".
Mandatory:

  • ADC4: activate the 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
  • NVIC: verify NVIC settings

Optional:

  • USART1: set mode to asynchronous
  • GPDMA1: configure channels 0 & 1
ADC4 By default, PHY calibration is based on temperature. Therefore, the temperature sensor channel must be activated.
CRC The cyclic redundancy check is used to verify Bluetooth® Low Energy data transmission or storage integrity.
RAMCFG Activating an SRAM is mandatory for the application. We dynamically modify the RAM configuration (System Clock Manager (SCM) module). This allows us to manage cases where we use low power, for example.
ICACHE The instruction cache (ICACHE) is introduced on the C-AHB code bus of the ARM Cortex-M33® processor to improve performance when fetching instructions and data from internal memories.
RNG The random number generator (RNG) provides the application with full entropy outputs as 32-bit samples. It is necessary to activate it, because the link layer regularly requests RNG.
RCC Reset and Clock Control manages the different kind of reset and generates all clocks for the bus and peripherals.
RF Activating an SRAM is mandatory for the application. We dynamically modify the RAM configuration (System Clock Manager (SCM) module). This allows us to manage cases where we use low power, for example.
RTC The real-time clock (RTC) provides an automatic wake-up to manage all low-power modes.
NVIC All interrupts including the core exceptions are managed by the nested vectored interrupt controller (NVIC).
USART1 USART1 is enabled to allow the display of traces on a terminal.
GPDMA1 The general purpose direct memory access controller (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.


IP list
Connectivity WBA CMX IP List.jpg

4.2.1. ADC4

The 12-bit Analog to Digital Converter (ADC4) has external and two internal (temperature sensor, voltage reference measurement) channels and performs conversions in single-shot or scan modes.
By default, PHY calibration is based on temperature. Therefore, the temperature sensor channel must be activated.

puce1.png
Select ADC4
puce2.png
Check Temperature Sensor Channel
puce3.png
Set sampling Time Common 1 to 814.5 Cycles
ADC4 configuration
Connectivity WBA CMX ADC4 Configuration.jpg

4.2.2. CRC

The Cyclic Redundancy Check (CRC) is used to verify Bluetooth® Low Energy data transmissions or storage integrity.

puce1.png
Select CRC
puce2.png
Check Activated
CRC activation
Connectivity WBA CMX CRC Configuration.jpg

4.2.3. RAMCFG

The RAMs ConFiGuration Controller (RAMCFG) configures the features of the internal SRAMs.
Activating an SRAM is mandatory for the application. We dynamically modify the RAM configuration (System Clock Manager (SCM) module). This allows us to manage cases where we use low power, for example.

puce1.png
Select RAMCFG
puce2.png
Select RAMCFG SRAM1
RAMCFG Activation
Connectivity WBA CMX RAMCFG Configuration.jpg

4.2.4. ICACHE

The Instruction CACHE (ICACHE) is introduced on the C-AHB code bus of the ARM Cortex-M33® processor to improve performance when fetching instructions and data from internal memories.

The ICACHE configuration is done as follows:

puce1.png
Select ICACHE
puce2.png
Choose 1-way (direct mapped cache) in Mode
ICACHE Activation
Connectivity WBA CMX ICACHE Configuration.jpg

4.2.5. RNG

The Random Number Generator (RNG) provides the application with full entropy outputs as 32-bit samples. It is necessary to activate it, because the link layer regularly requests RNG.

puce1.png
Select RNG
puce2.png
Check Activated
puce3.png
Select the NVIC Settings panel
puce4.png
Check Enabled for RNG Global interrupt
RNG Activation
Connectivity WBA CMX RNG Configuration.jpg

4.2.6. RCC

Reset and Clock Control (RCC) manages the different kinds of reset and generates all clocks for the bus and peripherals.

puce1.png
Select RCC
puce2.png
Choose Crystal/Ceramic Resonator for HSE
puce3.png
Choose Crystal/Ceramic Resonator for LSE
puce4.png
Select the NVIC Settings panel
puce5.png
Check Enabled for RCC non-secure global interrupt
RCC Activation & Setup
Connectivity WBA CMX RCC Configuration.jpg

4.2.7. RF

Activating RF is mandatory to activate the link layer.

puce1.png
Select RF
puce2.png
Check Activated
RF Activation
Connectivity WBA CMX RF Configuration.jpg

4.2.8. RTC

The Real Time Clock (RTC) provides an automatic wake-up to manage all low-power modes. The timers for the application, and those of the link layer deep sleep manager (PHY shutdown), are based on the timer server utility. This utility is based on the RTC.

First:

puce1.png
Select RTC
puce2.png
Check Activate Clock Source
puce3.png
Check Activate Calendar
puce4.png
Set Alarm A to Internal Alarm A
puce5.png
Select the Parameter Settings panel
puce6.png
Set Bin Mode to Free running Binary mode
puce7.png
Set Asynchronous Predivider value to 31
RTC Configuration (1/2)
Connectivity WBA CMX RTC1 Configuration.jpg

Then:

puce1.png
Select the NVIC Settings panel
puce2.png
Check Enabled for RTC non-secure interrupt (in the Parameter Settings tab, SSRU Underflow Interrupt will be turned to Enabled automatically)
RTC Configuration (2/2)
Connectivity WBA CMX RTC2 Configuration.jpg


4.2.9. USART1

USART1 is enabled to allow the display of traces on a terminal.

puce1.png
Select USART1
puce2.png
Set Mode to Asynchronous
puce3.png
Select the Parameter Settings tab
puce4.png
In Advanced Parameters, set Over Sampling to 8 samples (no change to the other settings)
puce5.png
Once USART1 is activated, USART1_TX and USART1_RX are assigned to pin PB12 and PA8
USART1 Configuration (1/2)
Connectivity WBA CMX USART1 1 Configuration.jpg
puce6.png
Select the NVIC Settings panel
puce7.png
Check Enabled for USART1 global interrupt
USART1 Configuration (2/2)
Connectivity WBA CMX USART1 2 Configuration.jpg

4.2.10. GPDMA1

The General Purpose Direct Memory Access (GPDMA) controller is a bus master and system peripheral. 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.

puce1.png
Select GPDMA1
puce2.png
Set Channel 0 and Chanel 1 to Standard Request Mode
GPDMA1 Configuration (1/4)
Connectivity WBA CMX GPDMA 14 Configuration.jpg


puce1.png
Select the CH0 panel
puce2.png
In Request Configuration, set Request to USART1_TX
puce3.png
In Channel Configuration, set Direction to Memory to Peripheral
puce4.png
In Source Data Setting, set Source Address Increment After Transfer to Enabled
GPDMA1 Configuration (2/4)
Connectivity WBA CMX GPDMA 24 Configuration.jpg


puce1.png
Select the CH1 tab
puce2.png
In Request Configuration, set Request to USART1_RX
puce3.png
In Channel Configuration, set Direction to Peripheral to Memory
puce4.png
In Destination Data Setting, set Destination Address Increment After Transfer to Enabled
GPDMA1 Configuration (3/4)
Connectivity WBA CMX GPDMA 34 Configuration.jpg


puce1.png
Select the All Channels tab
puce2.png
The panel shows the channel configurations
GPDMA1 Configuration (4/4)
Connectivity WBA CMX GPDMA 44 Configuration.jpg


4.2.11. NVIC

The Nested Vector Interrupt Controller (NVIC) and the processor core interface are closely coupled, enabling low-latency interrupt processing and efficient processing of late-arriving interrupts. The NVIC manages all interrupts including core exceptions.

puce1.png
Select NVIC
puce2.png
Check Enabled for all necessary interrupts
puce2.png
Set the preemption priorities
NVIC Configuration
Connectivity WBA CMX NVIC Configuration.jpg

4.3. Clock configuration

In the Clock Configuration tab, run the automatic clock issue solver (if requested).

The following configuration is defined for the initial startup phase. At runtime, clocks will be managed dynamically by the System Clock Manager (SCM) module.

Connectivity WBA CMX Clock Configuration 12.jpg

Then:

puce1.png
ADC4 Clock Mux on HCLK1
puce2.png
RTC Clock Mux on LSE
puce3.png
System Clock Mux on HSE
puce4.png
Input Frequency = 32MHz and divided by 2 for HSE, PLL1 *N on x8
puce5.png
Radio Sleep Timer Clock Mux on LSE
puce6.png
RNG Clock Mux on HSI
puce7.png
USART1 Clock Mux on HSI (reachable only when USART1 is turned on)
Clock configuration
Connectivity WBA CMX Clock Configuration 22.jpg

5. BLE GAP/GATT Custom application configuration

Now, we can start configuring and defining the STM32 Wireless Personal Area Network (WPAN).

  • The Bluetooth® Low Energy Peripheral Custom Template GATT Server Application can be defined:
    • on STM32WBA.
    • with STM32CubeMX (starting 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 wireless interface[6].

5.1. Enable BLE

To configure your application :

puce1.png
Select STM32_WPAN
puce2.png
In the Mode panel, chose Select and configure your Server application
STM32_WPAN Mode and Configuration
Connectivity WBA CMX STM32WPAN.jpg


5.2. Advertising configuration

puce1.png
Select the Configuration tab, open Application parameters, and set CFG_GAP_DEVICE_NAME to your application name, for example "MY_APPLI".


STM32_WPAN Interface: Bluetooth® Low Energy advertising configuration
Connectivity WBA CMX STM32WPAN ADV Configuration 24.jpg


This array is defined in the app_ble.c file with the following code:

static const char a_GapDeviceName[] = {  'M', 'y', '_', 'A', 'p', 'p', 'l', 'i' }; /* Gap Device Name */

In the generated code, these parameters are defined in the app_conf.h file:

#define ADV_INTERVAL_MIN                  (0x0080)
#define ADV_INTERVAL_MAX                  (0x00A0)
#define ADV_LP_INTERVAL_MIN               (0x0640)
#define ADV_LP_INTERVAL_MAX               (0x0FA0)
#define ADV_TYPE                          ADV_IND
#define ADV_FILTER                        NO_WHITE_LIST_USE

The advertising parameters are defined in the BLE Advertising tab:

puce2.png
The advertising configuration data are located in the app_conf.h file.
puce3.png
The advertising elements data are located in the app_ble.c file.
STM32_WPAN Interface: Bluetooth® LE Advertising tab
Connectivity WBA CMX STM32WPAN ADV Configuration 14.jpg



Open Advertising elements, included in the advertising packet payload, and:

puce1.png
set the elements you want to add to the advertising packet payload to “yes”.
puce2.png
enter the value for these elements.
STM32_WPAN Interface: Advertising elements
Connectivity WBA CMX STM32WPAN ADV Configuration 34.jpg


The generated code corresponding to the advertising packet elements is located in the 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 /*  */,
};

In this example, we configure 2 advertising elements (advertising packet structure length = 25 bytes):

  • Complete local name
  • Manufacturer-specific data

The advertising information is represented by the advertising data elements, which are standardized on the Bluetooth SIG.

The manufacturer-specific data are updated at runtime (specific function in the app_ble.c file). More details are available here: BlueST SDK v2

Warning white.png Warning
Do not oversize the length of the a_AdvData array (ad_data[]).

The size of this array is automatically calculated by STM32CubeMX and can't exceed 28 bytes


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 the SERVICEx panel). Each service and characteristic is added with the XXX_Init(void) function (XXX = service short name (capitalized), defined in the SERVICEx panel), using :

  • aci_gatt_add_service(…) for services.
  • aci_gatt_add_char(…) for characteristics.

5.3.1. BLE Applications and Services tab

To start defining the Bluetooth® Low Energy application:

puce1.png
Select the BLE Applications and Services panel.
puce2.png
Enter the number of services to define (one in our example).
puce3.png
A new tab is created for each service to configure.
Bluetooth® LE Applications and Services tab
Connectivity WBA CMX STM32WPAN Applications and Services.jpg

5.3.2. Service definition

Each service has to be configured in a dedicated tab (named SERVICE1 to SERVICE25).

  • Up to 25 characteristics per service
  • UUID type can be defined as 16- or 128-bit (full or reduced)
  • UUID definition
  • Type value is primary or secondary service

Once the number of services has been defined (in this example, we defined only one service with two characteristics), update the service information:

puce1.png
Select the SERVICE1 tab.
puce2.png
Set the number of characteristics and all the parameters required to define the service.
Service definition
Connectivity WBA CMX STM32WPAN Service Definition.jpg

5.3.3. Characteristic definition

For each characteristic, the following parameters must be defined:

  • General
  • Properties
  • Permissions
  • GATT events

In our example, the service we defined has the following 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



These characteristics have to be defined as shown in the image below:

SERVICE1 characteristic definition
Connectivity WBA CMX STM32WPAN Characteristic Definition.jpg


Info white.png Information
If UUID type is set to 128 bits, reduced, the UUID value (on 16 bits) is encapsulated in a 128-bit data by the COPY_xxx_UUID macro (where xxx is the long name of the service or characteristic).

For example, an UUID of 0xFE41 is encapsulated as follows:
0x00,0x00,0xfe,0x41,0x8e,0x22,0x45,0x41,0x9d,0x4c,0x21,0xed,0xae,0x82,0xed,0x19

If the UUID type is set to 16 bits, the UUID value is used as is to create the service or characteristic.

5.4. Application Configuration

All the Application Configuration topics are reachable when :

puce1.png
Configuration pane has been selected
puce2.png
Open and configure the Application configuration chapters
Application Configuration (1/12)
Connectivity WBA CMX STM32WPAN Application Configuration 1-12.jpg


For the next parts, the default values are recommended.

5.4.1. Project IP's Configuration

To display Application configuration recommendations:

puce1.png
Select Configuration tab
puce2.png
Select Application configuration recommandation line
puce3.png
Click on information logo or left click on Application configuration recommandations
puce4.png
Display recommendations
Application Configuration (2/12)
Connectivity WBA CMX STM32WPAN Application Configuration 2-12.jpg


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.

puce1.png
Open Application parameters
puce2.png
Turn PAIRING_PARAMETERS ON, to configure the Pairing parameters
Application Configuration (3/12)
Connectivity WBA CMX STM32WPAN Application Configuration 3-12.jpg


5.4.3. BLE Stack

puce1.png
Open Application parameters
puce2.png
Set BLE stack parameters
Application Configuration (4/12)
Connectivity WBA CMX STM32WPAN Application Configuration 4-12.jpg


5.4.4. Low Power

puce1.png
Open Low Power
puce2.png
Define Low Power parameters
Application Configuration (5/12)
Connectivity WBA CMX STM32WPAN Application Configuration 5-12.jpg


5.4.5. Traces

puce1.png
Open Traces
puce2.png
Define Traces parameters
Application Configuration (6/12)


5.4.6. Log level

puce1.png
Open Log level
puce2.png
Define Traces parameters
Application Configuration (7/12)
Connectivity WBA CMX STM32WPAN Application Configuration 7-12.jpg


5.4.7. NVM

puce1.png
Open NVM
puce2.png
Define NVM parameters
Application Configuration (8/12)
Connectivity WBA CMX STM32WPAN Application Configuration 8-12.jpg


5.4.8. RT GPIO debug

puce1.png
Open RT GPIO debug
puce2.png
Define RT GPIO debug parameters
Application Configuration (9/12)
Connectivity WBA CMX STM32WPAN Application Configuration 9-12.jpg


5.4.9. HW Radio

puce1.png
Open HW Radio
puce2.png
Define HW Radio parameters
Application Configuration (10/12)
Connectivity WBA CMX STM32WPAN Application Configuration 10-12.jpg


5.4.10. HW_RNG

puce1.png
Open HW_RNG
puce2.png
Define HW_RNG parameters
Application Configuration (11/12)
Connectivity WBA CMX STM32WPAN Application Configuration 11-12.jpg


5.4.11. Memory manager

puce1.png
Open Memory manager
puce2.png
Define Memory manager
Application Configuration (12/12)
Connectivity WBA CMX STM32WPAN Application Configuration 12-12.jpg


5.5. Platefrom Settings

BSP settings :

puce1.png
Open Platform Setting tab
puce2.png
Set Serial Link for Traces to USART : Asynchronous
puce3.png
And USART1
Platform Settings
Connectivity WBA CMX STM32WPAN Platform Settings.jpg


6. Project Configuration

All the project configuration is done on the Project Manager pane within three sections:

  • Project
  • Code generator
  • Advanced Settings
puce1.png
Select Project Manager pane
puce2.png
In Project window
puce3.png
Define the project name
puce4.png
Chose the project location
puce5.png
Select the Toolchain IDE and version
puce6.png
Define the linker settings

Depending on your work organization you can choose not to use the default firmware location. In this case :

puce7.png
Uncheck Use Default Firmware Location
puce8.png
To define your Firmware location
Project Configuration (1/4)
Connectivity WBA CMX Project Configuration 1-4.jpg


Management of files, packages and embedded software packs are done from Code Generator panel.

puce1.png
Select Code Generator pane
puce2.png
Select Add necessary files as reference in the toolchain project configuration files
puce3.png
Check :
  • Keep User Code when re-generating
  • Delete previously generated files when not re-generated
Project Configuration (2/4)
Connectivity WBA CMX Project Configuration 2-4.jpg


Then, in the Advenced Setting tab :

puce1.png
To put the functions in the desired order, select the function line
puce2.png
And use the arrows
Project Configuration (3/4)
Connectivity WBA CMX Project Configuration 3-4.jpg


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)
Connectivity WBA CMX Project Configuration 4-4.jpg


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
Connectivity WBA CMX STM32WBA Nucleo Board.jpg


7.1. User button and LED pinout

Connectivity WBA CMX Leds Pinout.jpg
Connectivity WBA CMX Button Pinout.jpg

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

For more information about buttons use cases for the p2pServer application, click here .


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 :

puce1.png
Click on Pinout view
puce2.png
Open PB4 configuration
puce3.png
Chose GPIO Output
Blue LED Pinout


For the red LED :

puce1.png
Open PB8 configuration
puce2.png
Chose GPIO Output
Red LED Pinout
Connectivity WBA CMX Pinout Red Led.jpg


For the green LED :

puce1.png
Open PA9 configuration
puce2.png
Chose GPIO Output
GreenLED Pinout
Connectivity WBA CMX Pinout Green Led.jpg


Once the three Leds (Blue, Green, Red) have been added, their configuration can be done :

puce1.png
From under Pinout and Configuration tab
puce2.png
Click on GPIO window
puce2.png
Select the GPIO line (PB4, PA9 or PA8)
puce3.png
Configure the GPIO line pane as:
  • GPIO output level : Low
  • GPIO mode : Output Push Pull
  • GPIO Pull-up/Pull-down : No pull-up and no pull-down
  • Maximum output speed : High
  • User Label : Blue_Led (PB4), Green_Led (PA9), or Red_Led (PB8)
LEDs Configuration
Connectivity WBA CMX Pinout LEDs Configuration.jpg


7.3. Buttons setup

For B1 setup go to Pinout and Configuration window, then :

puce1.png
Open PC13 configuration
puce2.png
Chose GPIO_EXTI13
B1 Pinout
Connectivity WBA CMX Pinout Button1.jpg


For B2 setup :

puce1.png
Open PB6 configuration
puce2.png
Chose GPIO_EXTI6
B2 Pinout
Connectivity WBA CMX Pinout Button2.jpg


For B3 setup :

puce1.png
Open PB7 configuration
puce2.png
Chose GPIO_EXTI7
B3 Pinout
Connectivity WBA CMX Pinout Button3.jpg


Once the three Buttons (B1, B2, B3) have been added, their configuration can be done:

puce1.png
From under Pinout and Configuration tab
puce2.png
Click on GPIO window
puce2.png
Select the GPIO line (PC13, PB6 or PB7)
puce3.png
Configure the GPIO line pane as:
  • Pin Privilede access : Non priviliged access
  • GPIO mode : External Interrupt Mode with Rising edge
  • GPIO Pull-up/Pull-down : Pull-up
  • User Label : B1 (PC13), B2 (PB6) or B3 (PB7)
Buttons Configuration
Connectivity WBA CMX Pinout Buttons Configuration.jpg


7.4. NVIC Configuration

Once buttons have been defined, configure NVIC:

puce1.png
Go to NVIC setting interface
puce2.png
Enable all the EXTI linex (B1, B2 and B3) needed Interrupt
puce2.png
Set the Preemption priority (set to 9 in our example)
NVIC Configuration


8. Code Generation

Once configuration is done in STM32CubeMX:

puce1.png
Code can be generated by STM32CubeMX
puce2.png
Open the project in the IDE (if not done already)
Code Generation
Connectivity WBA CMX Code Generation.jpg


Info white.png Information

It is possible to modify the default IDE in the Project Manager window, Project pan, and then Toolchain / IDE.

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
Connectivity WBA CMX Files to Update.jpg


  • 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 */
  CFG_TASK_BUTTON_1,
  CFG_TASK_BUTTON_2,
  CFG_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, ADV_TIMEOUT_MS);
/* 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, ADV_TIMEOUT_MS);
/* 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, ADV_TIMEOUT_MS);
  }
  else
  {
    UTIL_SEQ_SetTask( 1<<CFG_TASK_SEND_NOTIF_ID, CFG_SEQ_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, ADV_TIMEOUT_MS);
  }
 
  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_SEQ_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 for more details about it refer to : UM1718 User Manual section 6.4.

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
Connectivity WBA CMX extSettings file.jpg


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:

Connectivity WBA CMX Workspace.jpg


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