Custom BLE profile on STM32WB microcontrollers
In this article, we present the needed steps for developing a custom BLE profile on STM32WB microcontrollers, as a companion text of our public repository with examples for STM32WB55 and STM32WB15. On these examples, we have developed a custom BLE UART service, and the firmware, basically echoes the data received.
STMicroelectronics is a global Integrated Device Manufacturer (IDM), whose products are focus on smart mobility, power and energy, and IoT connectivity. In its portfolio, the STM32WB series is composed by a set of dual-core, multiprotocol wireless STM32WB microcontrollers, supporting Bluetooth ® Low Energy, Zigbee®, Thread ®, and Matter connectivity.
A Blue Thing In The Cloud, has the development of new BLE devices on its DNA. We have it even in our company name. That is why we are development partners of one of the most important BLE semiconductor manufacturer, like Nordic Semiconductors. Of course, we also have a huge experience with the technology offered by other manufacturers, like STMicroelectronics.
We have included 2 examples, because the STM32WB55, is the device of this family with more resources, so we present an example with FreeRTOS, and STM32WB15 is the smallest one, so we present the same in a bare metal implementation.
In case you are not familiar with Bluetooth Low Energy, you can skip this part. We present here a basic introduction of BLE, so you can quickly understand the examples.
Bluetooth is a wireless connectivity technology based on the IEEE 802.15 standard and managed by the Bluetooth Special Interest Group (SIG), which is responsible for defining and updating Bluetooth specifications, managing qualification programs and protecting the trademarks.
BLE focuses on reducing the power consumption while maintaining the same operating range as the classic Bluetooth.
The GAP provides a full standard framework for controlling a BLE device in point-to-point or broadcast (point to many) communication. GAP is in responsible for defining the device address, managing data broadcast, connections and security.
It defines the device role in the BLE network topology. Mainly, it defines if the device is a central, or a peripheral. There are other profiles like broadcaster and observer, but they are not relevant in this text.
Basically, a BLE Central Device connects to peripherals for reading and writing data. A BLE Peripheral Device advertises its existence, allowing BLE Central Devices to connect it. Once connected, it allows to read and write data.
These read and write operations are performed in characteristics, that are part of the services. The set of services, characteristics, and its attributes are part of the device GATT.
Therefore, the services, each of them with several characteristics, compose a GATT Additionally, the definition of a characteristic needs the declaration if its value attribute. The possible attribures are read, write, notify, or indicate.
We refer the reader to the shared links, and related pages to know more about BLE.
Custom BLE Profile on STM32WB microcontrollers
As an example of how to create a new BLE Peripheral device with custom services and characteristics, we have developed one of the most commonly custom profile example for the microcontrollers STM32WB15 and STM32WB55: a BLE Peripheral device with a custom BLE UART service, whose characteristics are RX and TX. From this example, we invite you to develop your custom BLE profile on STM32WB microcontrollers.
These project are publicly available in our repository.
The following text explain its code files focusing on the BLE custom profile development, so you could quickly develop your own minimal viable product. For further details like low power management, bootloader, testing, etc. Please feel free to contact us.
This file is in charge of the BLE stack initialization.
Here, you can see all the initial BLE configuration, you can change these parameters to have more services, or to increase the characteristics maximum length allowed, among other things.
In this function you should call the functions for initailizing your custom services. In our case, we call the Service_UART_Init function, we will explain it later.
Once the system has started its BLE stack, this function will be called, and here the user should call the functions of the services that define the GATT of its device.
Basically, we would place here all the device configuration parameters. In these examples, you can configure the BLE device name.
Here we define the custom service. First, please take a look at the header file, you need to define the UUIDs for the service and its characteristics, and you need data structures for its handlers.
The next image shows the values we have randomly chosen for them in this example.
We define the characteristics maximum length Service_UART.h
These values should not exceed 248 bytes. In this example, we set it to 64 bytes.
Adding the new service
Implementing the service… First, it is important to know that for dealing with a service, we need to have a context for it. Additionally, we must register a callback function which will be executed each time there is a new event for this service. For instance, when a central device writes something in our write characteristics.
That is why the Service_UART_Handler_Event function exist. We will explain it later. Just now, you need to know that you need to register this callback function. The next statement does this in the Service_UART_Init function
The next steps for performing the service initialization is to prepare the context, which is basically a memory space for the dynamic information of the service. The following statement declares the context.
Please mind that the STM32WB microcontrollers are dual core, and one of the cores is in charge of execution of the BLE stack, so you need to declare the context for the services using the above directive, so the core in charge of the BLE stack, can access to it.
Now that we have the UUID, and the context for the service, we can add to the device GATT the new service, by calling the funtion aci_gatt_add_service
The following image shows the statements adding the service
Adding the characteristics
After adding the service to the GATT, you should add the characteristics to the service, with its specific attributes (read, write…)
The following image shows how we did it, remarking where you should set the attributes for each characteristic.
In the code, we did it, just after adding the new service. And we recommend to do it in this way.
After adding the service, we need a way for writting values in the characteristics whose values are read, notify or indicate; and a way for reading values on the characteristics with write attribute.
Service_UART_Update_Characteristic is our implementation of a function in charge of writing a new value in a notify characteristic. Our notify characteristic is SERVICE_UART_UART_TX, what would be the TX line in an UART port.
Initially, we talked about the Service_UART_Handler_Event function. Exploring it, you will realize that it is in charge of reading the values that the central device writes on our RX characteristic. In this example, we only make an echo, since it is a basic demonstration of custom BLE profile on STM32WB microcontrollers. You should do any related action with incoming data here.
If you are planning to develop a new device with BLE functionality, we would like to invite you to contact us. We will willingly bring you our expertise, and we will be happy contributing to your success.