STM32WBA Bluetooth® LE - STM32CubeMX Application Conception

Revision as of 15:38, 12 May 2023 by Registered User (→‎Enable traces)

Click here for Bluetooth® Low Energy Overview.

1. Introduction

STM32CubeMX tool is a graphical tool that helps you to generate a first application targeting the MCU of your choice, with initialization code based on the configuration you specify. In the tools interface, you can select the right 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 custom application for STM32WBA52CG MCU using STM32CubeMX software.

2. Build a Bluetooth® Low Energy application on STM32WB with CubeMX

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
Connectivity WBA CMX 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 SW1 on Nucleo board send 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 STM32WB52CG
Initialize a CubeMX project targeting STM32WB52GG platform.

Step by step 2 logo.png

Step 2: STM32WBA IP configuration
Enable required system resources and peripherals to make BLE application to work.

Step by step 3 logo.png

Step 3: Clock configuration
Setup project clocks.

Step by step 4 logo.png
Step 4: Project Setup
Define project settings for C code generation as project name, IDE, Firmware location.

Step by step 5 logo.png
Step 5: Bluetooth® LE GAP/GATT Custom Application Configuration
Define BLE Application as Advertising parameters, Services and Characteristics.


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

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
Connectivity WBA CMX Hardware Presentation.jpg


4. CubeMX initialization for P-NUCLEO-WB55

4.1. STM32CubeMX initial setup

Open STM32CubeMX and start a new project from the Access to MCU selector button

New Project Menu
Connectivity wiki photo 03.png


Chose the MCU and then start the new project:

puce1.png
Click on the Series tab
puce2.png
Check STM32WB in MCU/MPU Selector tab
puce3.png
Select the STM32WB55RG part number
puce4.png
Start the project
Project Interface
Connectivity WBA CMX Project Interface.jpg


Start the new project without TrustZone activated

Connectivity WBA CMX Trust Zone Activation.jpg

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
Connectivity WBA CMX pinout Config Interface.jpg


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
Connectivity WBA CMX IP List.jpg

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.

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

4.2.2. CRC

The Cyclic Redundancy Check (CRC) is used to verify data transmission or storage integrity.

puce1.png
Select CRC
puce2.png
Activate it
CRC activation
Connectivity WBA CMX CRC Configuration.jpg

4.2.3. RAMCFG

The RAMs ConFiGuration Controller (RAMCFG) configures the features of the internal SRAMs

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 C-AHB code bus of Cortex-M33 processor to improve performance when fetching instruction and data from internal memories.

Configuration of ICACHE is done as follows:

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

4.2.5. RNG

The Random Number Generator (RNG) provides full entropy outputs to the application as 32-bit samples.

puce1.png
Select RNG
puce2.png
Activate it
puce3.png
Select NVIC panel
puce4.png
Enable RNG Global interrupt

RNG Activation
Connectivity WBA CMX RNG Configuration.jpg

4.2.6. RCC

Reset and Clock Control (RCC) manages the different kind 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 NVIC panel
puce5.png
Enable RCC non-secure global interrupt
RCC Activation & Setup
Connectivity WBA CMX RCC Configuration.jpg

4.2.7. RF

Activate RF

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

4.2.8. RTC

Real Time Clock (RTC) provides an automatic wakeup to manage all low-power modes.

puce1.png
Select RTC
puce2.png
Activate Calendar
puce3.png
Set Alarm A to Internal Alarm A
puce4.png
Select Parameter Settings tab
puce5.png
Set Asynchronous Predivider value to 31
puce5.png
Set Bin Mode to Free running Binary mode
RTC Configuration (1/2)
Connectivity WBA CMX RTC1 Configuration.jpg
puce8.png
Select NVIC Settings tab
Enable RTC non-secure interrupt (in 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 display of traces on a terminal.

puce1.png
Select USART1
puce2.png
Turn Mode to Asynchronous
puce3.png
Select Parameters Settings tab
puce4.png
In Advanced Parameters, set Over Sampling to 8 samples (other settings are already fine)
puce5.png
Once USART1 is activated, USART1_TX and USART1_RX are affected to pin PB12 and PA8
USART1 Configuration (1/2)
Connectivity WBA CMX USART1 1 Configuration.jpg
puce6.png
Select RF
puce7.png
Activate RF
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. 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.

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
In CH0 tab
puce2.png
Under Request Configuration, set Request to USART1_TX
puce3.png
Under Channel Configuration, set Direction to Memory to Peripheral
puce4.png
In Source Data Setting, enable Source Address Increment After Transfer
GPDMA1 Configuration (2/4)
Connectivity WBA CMX GPDMA 24 Configuration.jpg



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



puce1.png
In All Channels tab
puce2.png
The channels configuration shall be displayed
GPDMA1 Configuration (4/4)
Connectivity WBA CMX GPDMA 44 Configuration.jpg


4.2.11. NVIC

The Nested Vector Interrupt Controller (NVIC) ans the processor core interface are closely coupled, enabling low-latencyinterrupt processing and efficient processing of late arriving interrupts. All interrupts including the core exceptions are managed by the NVIC.

puce1.png
Go to NVIC setting interface
puce2.png
Enable all the needed Interrupt
puce2.png
Set the Preemption priority
NVIC Configuration
Connectivity WBA CMX NVIC Configuration.jpg

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.

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
PLL1 *N on x8
puce5.png
Radio Sleep Timer Clock Mux on LSE
puce4.png
RNG Clock Mux on HSI
puce5.png
USART1 Clock Mux on HSI (reachable only when USART1 turned ON)
Clock configuration
Connectivity WBA CMX Clock Configuration 22.jpg

4.4. Project manager

All the project configuration is done on the Project Manager pane within three sections, and done as follows :

4.4.1. Project

puce1.png
Configure the project
puce2.png
Define the project name
puce3.png
Chose the project location
puce4.png
Select the Toolchain IDE and version
puce5.png
Define linker settings
puce6.png
Use default FW location
Project configuration
Connectivity wiki photo 15.png


4.4.2. Code generator

Manages files, packages and embedded software packs

Project generation
Connectivity wiki photo 16.png


4.4.3. Advanced settings

Definition of drivers to use (HAL/LL) and generated function calls.

  • Uncheck Do Not Generate Function Call checkbox for APPE_Init
Advanced settings interface
Connectivity wiki photo 17.png

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].

5.1. Enable BLE

To configure your application :

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


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
Connectivity WBA CMX STM32WPAN ADV Configuration 14.jpg


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
Connectivity WBA CMX STM32WPAN ADV Configuration 24.jpg


In Advertising elements, included in the advertising packet payload :

puce1.png
Turn to “yes” the elements to add in the advertising packet payload
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 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)

Warning white.png Warning
Pay attention to not oversize the ad_data[ ] length array.

This array size 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 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 :

puce1.png
Go to BLE Applications and Services tab,
puce2.png
Enter the number of services to define (one in our example),
puce3.png
Note : For each number of service, a tab to configure it is created.
Bluetooth® LE Applications and Services
Connectivity WBA CMX STM32WPAN Applications and Services.jpg

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.

puce1.png
From 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. 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
Connectivity WBA CMX STM32WPAN Characteristic Definition.jpg


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

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

If UUID type is 16bits, the UUID value is used as this 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


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
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
puce7.png
Uncheck Use Default Firmware Location
puce8.png
To define your Firmware location a voir … si pas default FW location
Project Configuration (1/4)
Connectivity WBA CMX Project Configuration 1-4.jpg





Go to USART1 setup interface and select Asynchronous Mode:

USART Setup Interface
Connectivity wiki photo 47.png


Then, go to DMA Settings tab puce1.png, click on Add button puce2.png and select USART1_TX puce3.png.

USART Setup : DMA Settings
Connectivity wiki photo 48-bis.png


Ensure DMA1 Channel1 is selected, and click on USART1_TX line to show DMA Request Settings.

USART Setup : DMA Settings 2
Connectivity wiki photo 49-bis.png


Go to NVIC Settings tab puce1.png and enable USART1 global interrupt puce2.png.

USART Setup : NVIC Settings
Connectivity wiki photo 50-bis.png


6.1. NVIC configuration

Go to NVIC Settings interface puce1.png and set DMA1 Channel 1 global interrupt Preemption Priority to 15 (lowest priority) puce2.png.
Check that USART1 global interrupt is enabled puce3.png.

Connectivity wiki photo 51-bis.png

6.2. USART1 pinout definition

Go to Pinout view puce1.png.
Set UASRT1_TX on PB6 and USART1_RX on PB7:

  • Click on PB6
  • Select USART1_TX in the list
  • Click on PB7
  • Select USART1_RX in the list

You can use the search located in the bottom right of the pinout view window puce2.png to find a pin or signal name easily (here PB6 and PB7)

Pinout View
Connectivity wiki photo 52.png


6.3. STM32_WPAN configuration

Go to STM32_WPAN setup interface and select the Configuration tab puce1.png.
Enable the application traces puce2.png, set CFG_DEBUG_TRACES_UART on hw_uart1 puce3.png.
Configure the debug traces to manage the different types of logs puce4.png.

STM32WPAN Setup
Connectivity wiki photo 54-bis.png


6.4. Project manager settings

Go to Project Manager interface puce1.png and select the Advanced Settings tab puce2.png.
Configure MX_UASRT1_UART_Init function puce3.png as:

  • Check Do Not Generate Function Call checkbox.
  • Uncheck Visibility (Static) checkbox.
MX_UASRT1_UART_Init function Settings
Connectivity wiki photo 55.png



Once the traces configuration is done in STM32CubeMX, the code can be generated by following the steps described in Code Generation chapter.

6.5. Add USER CODE section in app_entry.c

In order to make the application able to manage debug messages, app_entry.c file must be updated.
In MX_APPE_Init() function, add a call to APPD_Init() function into the USER CODE APPE_Init_1 section as follows:

void MX_APPE_Init( void )
{
  System_Init( );       /**< System initialization */

  SystemPower_Config(); /**< Configure the system Power Mode */

  HW_TS_Init(hw_ts_InitMode_Full, &hrtc); /**< Initialize the TimerServer */

/* USER CODE BEGIN APPE_Init_1 */
  APPD_Init();
/* USER CODE END APPE_Init_1 */
  appe_Tl_Init();	/* Initialize all transport layers */


Open a debug terminal as TeraTerm connected on USART1 to display application messages. Refer to TeraTerm Setup chapter.

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 SW1 and write operation on P2P Server service
STM32WB Nucleo board
Connectivity wiki photo 108.png


7.1. User button and LED pinout

Connectivity wiki photo 67.png

In the Nucleo board, LED pinout is:

  • Blue LED : PB5
  • Green LED: PB0
  • Red LED: PB1

Switch (user button) pinout is:

  • SW1: PC4
  • SW2: PD0
  • SW3: PD1

When used:

  • Switch pins are declared as GPIO_EXTIx (x = pin number)
  • LED pins are declared as GPIO_OUTPUT





7.2. Blue LED setup

Go to Pinout and Configuration -> Pinout View Interface puce1.png, click on PB5 puce2.png and select GPIO_OUTPUT puce3.png.

Blue LED Pinout
Connectivity wiki photo 69-bis.png


In pinout and configuration interface, go to the GPIO tab puce1.png.
Select the GPIO line corresponding to PB5 puce2.png and configure the PB5 configuration pane puce3.png as follows:

  • GPIO Mode: Output Push/Pull
  • GPIO Pull-up/Pull-down: No Pull-up and no pull-down
  • Maximum outpus speed: High
  • User Label: Blue_Led
Blue LED : GPIO Configuration
Connectivity wiki photo 71-bis.png


This generate the following Blue_Led GPIO pin and port definitions in main.h:

Blue LED : GPIO Configuration Code
wiki photo 71 code.png


7.3. SW1 button setup

Go to Pinout & Configuration -> Pinout View Interface puce1.png, click on PC4 puce2.png and select GPIO_EXTI4 puce3.png.

SW1 Button Pinout
Connectivity wiki photo 72-bis.png


In Pinout & Configuration interface, go to the GPIO tab puce1.png.
Select the GPIO line corresponding to PC4 puce2.png and configure the PC4 configuration pane puce3.png as follows:

  • GPIO Mode: External Interrupt Mode with Rising edge trigger detection
  • GPIO Pull-up/Pull-down: Pull-up
  • User Label: SW1_User
SW1 Button : GPIO Configuration
Connectivity wiki photo 74-bis.png


This generate the following SW1_User GPIO pin and port definitions in main.h:

SW1 Button : GPIO Configuration Code
wiki photo 74 code.png



Go to NVIC interface puce1.png and click on the NVIC tab puce2.png.
Enable the EXTI line4 interrupt puce3.png, this interrupt corresponds to SW1.

SW1 Button : GPIO Configuration
Connectivity wiki photo 75-bis.png


7.4. Code modification: User sections

Once your SW1 Button and Blue LED 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 CubeMX.

In order to manage SW1 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 wiki photo 78-bis.png


  • In app_conf.h:

Define the task for the characteristic My_Switch_Char of My_P2P_Server by adding code in CFG_Task_Id_With_HCI_Cmd_t User Code Section:

/**< Add in that list all tasks that may send a ACI/HCI command */
typedef enum
{
    CFG_TASK_ADV_CANCEL_ID,
#if (L2CAP_REQUEST_NEW_CONN_PARAM != 0)
    CFG_TASK_CONN_UPDATE_REG_ID,
#endif
    CFG_TASK_HCI_ASYNCH_EVT_ID,
/* USER CODE BEGIN CFG_Task_Id_With_HCI_Cmd_t */
    CFG_TASK_SW1_BUTTON_PUSHED_ID,                                              /* Code Line to add */
/* USER CODE END CFG_Task_Id_With_HCI_Cmd_t */
    CFG_LAST_TASK_ID_WITH_HCICMD,                                               /**< Shall be LAST in the list */
} CFG_Task_Id_With_HCI_Cmd_t;


  • In app_entry.c:

Define the callback for handling the interrupts from SW1 presses by adding code in FD_WRAP_FUNCTIONS User Code Section:

/* USER CODE BEGIN FD_WRAP_FUNCTIONS */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{                                                                                                 
  switch (GPIO_Pin)                                                                  
  {                                                                                             
    case BUTTON_SW1_PIN:                                                          
      APP_BLE_Key_Button1_Action();                                      
      break;                                                                                 
    default:                                                                                 
      break;                                                                                
  }                                                                                             
  return;                                                                                   
}                                                                                              
/* USER CODE END FD_WRAP_FUNCTIONS */


  • In app_ble.c:

Define function for SW1 action by adding code in FD_SPECIFIC_FUNCTIONS User Code Section:

/* USER CODE BEGIN FD_SPECIFIC_FUNCTIONS */
void APP_BLE_Key_Button1_Action(void)
{
  P2PS_APP_SW1_Button_Action();
}
/* USER CODE END FD_SPECIFIC_FUNCTIONS */


  • In app_ble.h:

Declare the APP_BLE_Button1_Action() function, in EF User Code Section:

/* Exported functions ---------------------------------------------*/
  void APP_BLE_Init( void );

/* USER CODE BEGIN EF */
void APP_BLE_Key_Button1_Action(void);        /* Code Line to add */
/* USER CODE END EF */


  • In custom_app.h:

Declare P2PS_APP_SW1_Button_Action function, in EF User Code Section:

/* Exported functions ---------------------------------------------*/
  void Custom_APP_Init( void );
  void Custom_APP_Notification( Custom_App_ConnHandle_Not_evt_t *pNotification );
/* USER CODE BEGIN EF */
  void P2PS_APP_SW1_Button_Action(void);        /* Code Line to add */
/* USER CODE END EF */


  • In custom_app.c:

Add SW1_Status variable in CUSTOM_APP_Context_t User Code Section:

/* Private typedef -----------------------------------------------------------*/
typedef struct
{
  /* My_P2P_Server */
  uint8_t               Switch_c_Notification_Status;
  /* My_Heart_Rate */
  uint8_t               Hrs_m_Notification_Status;
  /* USER CODE BEGIN CUSTOM_APP_Context_t */
  uint8_t               SW1_Status;                      /* Code Line to add */
  /* USER CODE END CUSTOM_APP_Context_t */

  uint16_t              ConnectionHandle;
} Custom_App_Context_t;

/* USER CODE BEGIN PTD */

/* USER CODE END PTD */


In the same file, update snippets shown. The following traces code is to indicate the Smartphone requests to enable or disable notifications and write requests on My_P2P_Server service.
In CUSTOM_STM_LED_C_WRITE_NO_RESP_EVT User Section:

/* Functions Definition ------------------------------------------------------*/
void Custom_STM_App_Notification(Custom_STM_App_Notification_evt_t *pNotification)
{
  /* USER CODE BEGIN CUSTOM_STM_App_Notification_1 */

  /* USER CODE END CUSTOM_STM_App_Notification_1 */
  switch(pNotification->Custom_Evt_Opcode)
  {
    /* USER CODE BEGIN CUSTOM_STM_App_Notification_Custom_Evt_Opcode */

    /* USER CODE END CUSTOM_STM_App_Notification_Custom_Evt_Opcode */

  /* My_P2P_Server */
    case CUSTOM_STM_LED_C_READ_EVT:
      /* USER CODE BEGIN CUSTOM_STM_LED_C_READ_EVT */

      /* USER CODE END CUSTOM_STM_LED_C_READ_EVT */
      break;

    case CUSTOM_STM_LED_C_WRITE_NO_RESP_EVT:
      /* USER CODE BEGIN CUSTOM_STM_LED_C_WRITE_NO_RESP_EVT */
      APP_DBG_MSG("\r\n\r** CUSTOM_STM_LED_C_WRITE_NO_RESP_EVT \n");
      APP_DBG_MSG("\r\n\r** Write Data: 0x%02X %02X \n", pNotification->DataTransfered.pPayload[0], pNotification->DataTransfered.pPayload[1]);
      if(pNotification->DataTransfered.pPayload[1] == 0x01)
      {
        BSP_LED_On(LED_BLUE);
      }
      if(pNotification->DataTransfered.pPayload[1] == 0x00)
      {
        BSP_LED_Off(LED_BLUE); 
      } 
     /* USER CODE END CUSTOM_STM_LED_C_WRITE_NO_RESP_EVT */
      break;


In CUSTOM_STM_SWITCH_C_NOTIFY_ENABLED_EVT and CUSTOM_STM_SWITCH_C_NOTIFY_DISABLED_EVT User Sections:

case CUSTOM_STM_SWITCH_C_NOTIFY_ENABLED_EVT:
      /* USER CODE BEGIN CUSTOM_STM_SWITCH_C_NOTIFY_ENABLED_EVT */
      APP_DBG_MSG("\r\n\r** CUSTOM_STM_BUTTON_C_NOTIFY_ENABLED_EVT \n");

      Custom_App_Context.Switch_c_Notification_Status = 1;        /* My_Switch_Char notification status has been enabled */
      /* USER CODE END CUSTOM_STM_SWITCH_C_NOTIFY_ENABLED_EVT */
      break;

    case CUSTOM_STM_SWITCH_C_NOTIFY_DISABLED_EVT:
      /* USER CODE BEGIN CUSTOM_STM_SWITCH_C_NOTIFY_DISABLED_EVT */
      APP_DBG_MSG("\r\n\r** CUSTOM_STM_BUTTON_C_NOTIFY_DISABLED_EVT \n");

      Custom_App_Context.Switch_c_Notification_Status = 0;        /* My_Switch_Char notification status has been disabled */
      /* USER CODE END CUSTOM_STM_SWITCH_C_NOTIFY_DISABLED_EVT */
      break;


Add code snippets in Custom_App_Init() function to register the send notification task that is started when SW1 button is pressed, in CUSTOM_APP_Init User Section:

void Custom_APP_Init(void)
{
  /* USER CODE BEGIN CUSTOM_APP_Init */
  UTIL_SEQ_RegTask(1<< CFG_TASK_SW1_BUTTON_PUSHED_ID, UTIL_SEQ_RFU, Custom_Switch_c_Send_Notification);

  Custom_App_Context.Switch_c_Notification_Status = 0;   
  Custom_App_Context.SW1_Status = 0;                 

  /* USER CODE END CUSTOM_APP_Init */
  return;
}


And code snippet to allow the task to run once SW1 is pressed, in FD_LOCAL_FUNCTIONS User Section:

/* USER CODE BEGIN FD_LOCAL_FUNCTIONS*/
  void P2PS_APP_SW1_Button_Action(void)
  {
    UTIL_SEQ_SetTask(1<<CFG_TASK_SW1_BUTTON_PUSHED_ID, CFG_SCH_PRIO_0);

    return;
  }
/* USER CODE END FD_LOCAL_FUNCTIONS*/


Add code snippet for sending notification request to the smart phone, in Switch_c_NS User Section:

void Custom_Switch_c_Send_Notification(void) /* Property Notification */
 {
  if(Custom_App_Context.Switch_c_Notification_Status)
  {
    Custom_STM_App_Update_Char(CUSTOM_STM_SWITCH_C, (uint8_t *)NotifyCharData);
    /* USER CODE BEGIN Switch_c_NS*/
    if (Custom_App_Context.SW1_Status == 0)
    {
      Custom_App_Context.SW1_Status = 1;
      NotifyCharData[0] = 0x00;
      NotifyCharData[1] = 0x01;
    }
    else
    {
      Custom_App_Context.SW1_Status = 0;
      NotifyCharData[0] = 0x00;
      NotifyCharData[1] = 0x00;
    }

    APP_DBG_MSG("-- CUSTOM APPLICATION SERVER  : INFORM CLIENT BUTTON 1 PUSHED \n");
    APP_DBG_MSG(" \n\r");
    Custom_STM_App_Update_Char(CUSTOM_STM_SWITCH_C, (uint8_t *)NotifyCharData);

    /* USER CODE END Switch_c_NS*/
  }
  else
  {
    APP_DBG_MSG("-- CUSTOM APPLICATION : CAN'T INFORM CLIENT -  NOTIFICATION DISABLED\n");
  }
  return;
}


  • In custom_stm.c:

Update Custom_STM_Event_Handler() function to manage My_LED_Char write, in CUSTOM_STM_Service_1_Char_1_ACI_GATT_ATTRIBUTE_MODIFIED_VSEVT_CODE User Section:

static SVCCTL_EvtAckStatus_t Custom_STM_Event_Handler(void *Event)
{
  []
 event_pckt = (hci_event_pckt *)(((hci_uart_pckt*)Event)->data);

  switch(event_pckt->evt)
  {
    case HCI_VENDOR_SPECIFIC_DEBUG_EVT_CODE:
      blecore_evt = (evt_blecore_aci*)event_pckt->data;
      switch(blecore_evt->ecode)
      {
        case ACI_GATT_ATTRIBUTE_MODIFIED_VSEVT_CODE:
        []
          else if(attribute_modified->Attr_Handle == (CustomContext.CustomLed_CHdle + CHARACTERISTIC_VALUE_ATTRIBUTE_OFFSET))
          {
            return_value = SVCCTL_EvtAckFlowEnable;
            /* USER CODE BEGIN CUSTOM_STM_Service_1_Char_1_ACI_GATT_ATTRIBUTE_MODIFIED_VSEVT_CODE */
            Notification.Custom_Evt_Opcode = CUSTOM_STM_LED_C_WRITE_NO_RESP_EVT;
            Notification.DataTransfered.Length=attribute_modified->Attr_Data_Length;
            Notification.DataTransfered.pPayload=attribute_modified->Attr_Data;
            Custom_STM_App_Notification(&Notification);
            /* USER CODE END CUSTOM_STM_Service_1_Char_1_ACI_GATT_ATTRIBUTE_MODIFIED_VSEVT_CODE */
          } /* if(attribute_modified->Attr_Handle == (CustomContext.CustomLed_CHdle + CHARACTERISTIC_VALUE_ATTRIBUTE_OFFSET))*/
          /* USER CODE BEGIN EVT_BLUE_GATT_ATTRIBUTE_MODIFIED_END */

          /* USER CODE END EVT_BLUE_GATT_ATTRIBUTE_MODIFIED_END */
          break;


7.5. ST BLE toolbox: P2P server notification and write

If you are not familiar with ST BLE ToolBox application, a first introduction is available on ST BLE Toolbox Application chapter.

1. Scan and connect
Open a serial terminal (see: TeraTerm Configuration chapter) and connect your smartphone to your board using ST BLE ToolBox application.

Once connected, the following message is displayed on TeraTerm.

P2P Server Connection logs
Connectivity wiki photo 94.png


2. P2P Server Notification
Search and open P2P Server service.
Enable P2P Notify, on characteristic FE42 to receive notification from the STM32WB Nucleo board, using SW1 button as configured in previous example.

ST BLE Toolbox: Enable P2P Notify
Connectivity wiki photo 96.png


  • When notifications have been enabled, the application displays the following message on the terminal:
Notification enabled logs
Connectivity wiki photo 97.png


  • In the same way, when notifications are disabled, the following debug message is displayed on the terminal:
Notification disabled logs
Connectivity wiki photo 98.png


Once notifications enabled, press SW1 button on Nucleo board to notify the P2P Server Characteristic.
The P2P Notify characteristic value toggles each time the SW1 button is pressed.

ST BLE Toolbox: Notify characteristic value
Connectivity wiki photo 100.png


3. P2P Write
Using FE41 (LED_C) characteristic which is defined as a Write Without Response property, the P2P service writes data to the STM32WB Nucleo Board.
Press WRITE button and select Hexadecimal format puce1.png, then define the data to write puce2.png and press SEND button puce3.png to write it in the LED_C characteristic.

ST BLE Toolbox: P2P Write
Connectivity wiki photo 102-bis.png


  • Writing 0x0000 in 0xFE41 characteristic switch the LED 1 OFF.
  • Writing 0x0001 in 0xFE41 characteristic switch the LED 1 ON.

On the debug terminal, the message with the written data is displayed.

P2P Write logs
Connectivity wiki photo 107.png

8. Code generation

Once configuration is done in STM32CubeMX, the code can be generated puce1.png:

Code Generation
Connectivity wiki photo 32.png


Project can then be open puce2.png:

Generated project pop-up
Connectivity wiki photo 33.png


Open Project with IAR IDE, (\EWARM\ Project.eww) and ensure project options are correctly defined:

IAR Project Setup
Connectivity wiki photo 34-bis.png
Connectivity wiki photo 36-bis.png
Connectivity wiki photo 38.png


Project build from IAR IDE:

  • Check there is no error when building the project from IAR.
Warning white.png Warning
Some build warnings could be listed due to declared functions but never referenced, or variables not used when pairing is off.
  • Connect the Nucleo board to the PC with USB cable.
  • Flash the binary file into the P-NUCLEO-WB55[7] board.
  • Run the application to make it advertise.
  • Connect MyCST application thanks to ST BLE ToolBox application. Refer to ST BLE Toolbox Application chapter.

9. TeraTerm configuration

This chapter describes how to setup TeraTerm in order to display traces from the STM32WB projects.
The ST-Link of the Nucleo board is displayed as a Virtual COM Port (as shown in the Device Manager window below).
USART1 pins are routed through this port, which is connected to serial terminal (TeraTerm) to display traces.

Device Configuration manager
Connectivity wiki photo 59.png


In TeraTerm interface, select the corresponding serial port:

TeraTerm Serial port selection
Connectivity wiki photo 60.png


Set the Serial Port configuration as follows:

TeraTerm Serial port configuration
Connectivity wiki photo 63.png


Once the TeraTerm is configured and connected to the Nucleo board you can run your code and the enabled logs must be displayed.

10. ST BLE toolbox application

The following chapter describes ST BLE ToolBox application utilization.

10.1. Scan and connect

When you launch ST BLE ToolBox smartphone application, it scans to search WB devices. On the scan interface, the name (MyCST) of the application previously generated and build using STM32CubeMX and IAR must be displayed once discovered.

Select the application by clicking on his name, then click on Connect button:

ST BLE Toolbox: scan interface
Connectivity wiki photo 41.png

10.2. Discover services and characteristics

When connected to MyCST, scroll on services to find the defined ones.

  • P2P Server Service:

Tap P2P Server to display the associated characteristics:

ST BLE Toolbox Services interface
Connectivity wiki photo 43-bis.png


As defined in STM32CubeMX we see P2P Server’s characteristics and associated properties:

puce1.png
Service P2P Server : UUID = 0xFE40
puce2.png
Characteristic 1 : UUID = 0xFE41 is Readable and Writable
puce3.png
Characteristic 2 : UUID = 0xFE42 is Notify
ST BLE Toolbox : P2P Server Characteristics interface
Connectivity wiki photo 44.png


  • Heart Rate Service:

Tap Heart Rate to display the associated characteristics.

ST BLE Toolbox Services interface
Connectivity wiki photo 45-bis.png


As defined in STM32CubeMX we see Heart Rate’s characteristics and associated properties (tap details puce1.png):

  • Service Heart Rate : UUID = 0x180D
  • Characteristic 1 : UUID = 0x2A37 is Notify
  • Characteristic 3 : UUID = 0x2A38 is Readable
  • Characteristic 2 : UUID = 0x2A39 is Writable
ST BLE Toolbox : Heart Rate Characteristics interface
Connectivity wiki photo 46.png


11. References