Bluetooth Knowledge Base

    Publish
     
      • Upgrading Gecko Bootloader with Slot address change

        arkalvac | 01/23/2018 | 10:44 AM

        Gecko Bootloader can be upgraded either via UART or via Bluetooth as described here:
        https://www.silabs.com/community/wireless/bluetooth/knowledge-base.entry.html/2017/04/26/upgrading_gecko_boot-IfFz

        The following article discusses the special case when you want to upgrade your Gecko Bootloader via Bluetooth with an image that has different slot configuration than the previous Gecko Bootloader you used on your device.

        To upgrade the bootloader with a new slot configuration is problematic, because the upgrade image is uploaded by the old bootloader to the old slot address, but after the bootloader upgrade the new bootloader tries to bootload the apploader image from the new address – this will definitely fail.

        The following workaround can be used to solve this issue:

        Suppose you want to upgrade from bootloader A, that has Slot0 address A, to bootloader B, that has Slot0 address B.

        1. you have a bootloader with Slot0 address A in your device. This will upload the upgrade image to address A.
        2. first you have to upgrade to a temporary multislot bootloader with Slot0 address B and Slot1 address A. This can bootload from address A but will upload the next upgrade image to address B.
        3. finally you have to upgrade to the single slot bootloader with Slot0 address B, as originally intended. This can bootload from address B.

         

        How to configure the temporary multislot bootloader:

        1. create a new bootloader project. Use Bluetooth in-place OTA DFU Bootloader or Internal/External storage bootloader, as you normally do.
        2. define the customer version string to N+1, where N is the version number of the original bootloader. You can do this by defining BOOTLOADER_VERSION_MAIN_CUSTOMER on the Other tab in the AppBuilder.
        3. On the Storage tab define the slots. Define Slot0 to the new address (with the new slot size), and Slot1 to the old address (with the old slot size).
        4. The multislot configuration needs a bootload info table that takes 8kB. It has to be defined somewhere outside of Slots and outside of the bootloader and apploader area. Go to Plugins page, select Common Storage, and define the Start address for bootload info to e.g. 8kB before the Slot with lower address. Make sure that the start address is aligned with the 2kB flash page size!
        5. press Generate to generate your project
        6. there is one more change needed. The bootload info table should be normally initialized by the app. This table tells which slots should be bootloaded in which order. Since there is no valid application image, however, after the bootloader upgrade, the bootloader code has to be modified:
        • -find storage-common/btl_storage.c in your project.
        • -right click on it and select „Copy Linked File into Project”. This will copy btl_storage.c and btl_storage.h into the project from the SDK.
        • -in storage-common_inc/btl_storage.h change to following line
          #include "bootloadinfo/btl_storage_bootloadinfo.h"

        to

          #include "plugin/storage/bootloadinfo/btl_storage_bootloadinfo.h"
        • -in storage-common/btl_storage.c change the following lines
          ret = storage_getBootloadList(slotIds, BTL_STORAGE_BOOTLOAD_LIST_LENGTH);
          if (ret != BOOTLOADER_OK) {
            BTL_DEBUG_PRINTLN("BI err");
            return ret;
          }

        to

          ret = storage_getBootloadList(slotIds, BTL_STORAGE_BOOTLOAD_LIST_LENGTH);
          if (ret != BOOTLOADER_OK) {
            BTL_DEBUG_PRINTLN("BI err");
            slotIds[0] = 0;
            slotIds[1] = 1;
          }

        This will ensure, that the bootloader will try to bootload from Slot0 and then from Slot1.

        7. build your project, and upgrade to this bootloader as normally, before upgrading to the final bootloader.

         

        The final bootloader can be configured as normally, but make sure that its version number is N+2.

      • NCP Host Implementation and Example

        Kevin_Fu | 01/18/2018 | 12:33 AM

        SoC Mode vs NCP Mode

         

        The Bluetooth SDK supports two developing modes, System-On-Chip (SoC) and Network Co-Processor (NCP). For SoC mode, all the application will run on a single EFR32 device. For NCP mode, a EFR32 device acts as the coprocessor, working together with a host controller. AN1042: Using the Silicon Labs Bluetooth® Stack in Network Co-Processor Mode has detailed description of the NCP mode. It’s recommended to read this application note before reading this article, which can give you a better understanding of NCP mode.

        Figure 1. SoC Mode

        Figure 2. NCP Mode

         

        BGLib and BGAPI

         

        • BGAPI is a custom binary protocol used to externally control our chipset and modules. BGAPI is a protocol specification only.
        • BGLib is an ANSI C reference implementation of the BGAPI binary protocol. BGLib only runs outside of our chipset and modules. BGLib assumes the host MCU is little-endian.

        When using SoC mode, it allows you to run an application right on the chipset or module and call the BGAPI directly. However, if using the NCP mode, the application runs on an external device – typically a microcontroller, everything can communicate over UART between the NCP host and NCP target.

         

        BGLIB_DEFINE

        BGLib uses a set of global variables that are defined using macro BGLIB_DEFINE(), found in gecko_bglib.h. The host application that uses BGLib must include BGLIB_DEFINE() in global scope (i.e. it must be placed outside any function implementation).

        BGLIB_DEFINE() is used to declare variables used for BGLib, it must be define globally.

        #define BGLIB_DEFINE()                                      \
          struct gecko_cmd_packet _gecko_cmd_msg;                   \
          struct gecko_cmd_packet _gecko_rsp_msg;                   \
          struct gecko_cmd_packet *gecko_cmd_msg = &_gecko_cmd_msg; \
          struct gecko_cmd_packet *gecko_rsp_msg = &_gecko_rsp_msg; \
          void (*bglib_output)(uint32_t len1, uint8_t* data1);      \
          int32_t (*bglib_input)(uint32_t len1, uint8_t* data1);    \
          int32_t (*bglib_peek)(void);                              \
          struct gecko_cmd_packet gecko_queue[BGLIB_QUEUE_LEN];     \
          int    gecko_queue_w = 0;                                 \
          int    gecko_queue_r = 0;
        
        • _gecko_cmd_msg – The instance to store the command message.
        • _gecko_rsp_msg – The instance to store the response message.
        • gecko_cmd_msg – Pointer to _gecko_cmd_msg instance.
        • gecko_rsp_msg – Pointer to _gecko_rsp_msg instance.
        • gecko_queue[BGLIB_QUEUE_LEN] – FIFO buffer to store the messages received from the NCP target.
        • gecko_queue_w – FIFO buffer write index, working with gecko_queue_r to indicate if there is new message stored in the queue, it offsets by one if a new message is received.
        • gecko_queue_r – FIFO buffer read index, working with gecko_queue_w to indicate if there is new message stored in the queue, it offsets by one if a new message is read out from the queue.
        • bglib_output, bglib_input, bglib_peek – Function pointers to writing to / reading from / peek UART.

        The symbol BGLIB_QUEUE_LEN defines the length of queue, it’s 30 by default and depends on the real use cases and allowed host memory usage.

         

        Operation Modes

        • Blocking mode – If this mode is used, BGLib will get blocked in waiting events from NCP target if there is no data to send nor events to handle. To use this mode, use gecko_wait_event() to check events and call the function BGLIB_INITIALIZE(OFUNC, IFUNC) in your initialization code.
        • Nonblocking mode – If this mode is used, BGLib will not get blocked if there is no data to send nor data to receive. To use this mode, use gecko_peek_event() to check events and call the function BGLIB_INITIALIZE_NONBLOCK(OFUNC, IFUNC, PFUNC) in your initialization code.

        It depends on the real use case which mode should be used. If there are many tasks not related to Bluetooth, nonblocking mode should be a better choice, because it will bypass the BGLib functions if there are no Bluetooth events to be handled and allows the MCU to process other tasks. The reason BGLib supports blocking mode is for symmetry purpose that the same code should work in both SoC and NCP modes, it’s recommended to use nonblocking mode because it gives the user better control of their application in most of the use cases.

        Figure 3. Blocking vs Nonblocking

         

        Function Mapping

        Below functions are used to read from and write to UART. BGLib accesses UART through function pointers so that the code is platform independent. User must map the function pointers to platform-specific UART transmit / receive routines when initializing BGLIb. This is done using macro BGLIB_INITIALIZE() or BGLIB_INITIALIZE_NONBLOCK(), depending if blocking or non-blocking mode is used.

        • void(*bglib_output)(uint32_t len1, uint8_t* data1);

        This is the callback function to send “len1” amount of data out via UART

        • int32_t (*bglib_input)(uint32_t len1, uint8_t* data1);

        This is the callback function to receive “len1” amount of data via UART

        • int32_t(*bglib_peek)(void);

        This is only required if using the nonblocking mode, this function is to peek the UART if there is any data valid.

         

        How BGLib works?

         

        Below 3 flowcharts show how BGLib works in details.

        Figure 4. Flowchart of Nonblocking function calling

        Figure 5. Flowchart of blocking function calling

        Figure 6. Flowchart of API calling

         

        Adding BGLib to Host MCU Project

         

        Preparation

        • Install Simplicity Studio 4 to your PC
        • Install Bluetooth SDK 2.7.0, which is available from the software update of Simplicity Studio 4

         

        Below is the step by step guide to add BGLib to a host MCU project.

        • Create a base project of the specified MCU.
        • There are some source and header files need to be added to the project, shown as below.
          • C:\SiliconLabs\SimplicityStudio\v4\developer\sdks\gecko_sdk_suite\v2.1\protocol\bluetooth_2.7\ble_stack\inc\common
            • bg_errorcodes.h
            • bg_gattdb_def.h
            • bg_types.h
            • gecko_configuration.h
          • C:\SiliconLabs\SimplicityStudio\v4\developer\sdks\gecko_sdk_suite\v2.1\protocol\bluetooth_2.7\ble_stack\inc\host
            • gecko_bglib.h
            • host_gecko.h
          • C:\SiliconLabs\SimplicityStudio\v4\developer\sdks\gecko_sdk_suite\v2.1\protocol\bluetooth_2.7\ble_stack\src\host
            • gecko_bglib.c
        • Implement the callback functions mentioned above.
        • Add “BGLIB_DEFINE();” to the macro definition area in your project.
        • Add BGLIB_INITIALIZE(user_output, user_input) or BGLIB_INITIALIZE_NONBLOCK(user_output, user_input, user_peek) to the initialization code, after that, it’s recommended to call gecko_cmd_system_reset(0); function to reset the NCP target.
        • Add below template to the while loop to handle all the events received from NCP target.
        static void appHandleEvents(struct gecko_cmd_packet *evt) {
        	if (NULL == evt) {
        		return;
        	}
        
        	/* Handle events */
        	switch (BGLIB_MSG_ID(evt->header)) {
        		case xxx:
        		break;
        		case xxx:
        		break;
        
        		…
        
        		default:
        		break;
        	}
        }
        
        While(1){
            ...
            /* Check for stack event. */
            evt = gecko_peek_event();
        	/* Run application and event handler. */
        	appHandleEvents(evt);
        	...
        }
        

         

        Example

         

        Contents

        Attachment is an example running on EFR32PG1 kit – BRD2500 Rev A01 (NCP host) and EFR32BG13 kit – BRD4104a Rev A00 (NCP target).

        • KBA_ncp_host_pg – Project for NCP host
        • KBA_ncp_host_example – Project for NCP target
        • KBA_ncp_host_pg.map – Map file of the KBA_ncp_host_pg project under compiler IAR and high size optimization.

         

        UART configuration

        • Baud rate: 115200
        • Data bits: 8
        • Stop bit: 1
        • Flow control: False
        • NCP host (EFR32PG1) UART pin configuration
          • TX pin – PD10, EXP_HEADER 9
          • RX pin – PD11, EXP_HEADER 11
        • NCP target (EFR32BG13) UART pin configuration
          • TX pin – PA0, EXP_HEADER 12
          • RX pin – PA1, EXP_HEADER 14

        Connection between NCP host and NCP target is shown below, see figure 5.

        NCP host expansion header                                NCP target expansion header

                 GND                                                       GND

        PIN 9 (PD10) – UART TX                                    PIN 14 (PA1) – UART RX

        PIN 11 (PD11) – UART RX                                   PIN 12 (PA0) – UART TX

        Figure 7. Connection between NCP host and target

         

        Verifying the example

        This example uses the nonblocking mode. You can import them to your Simplicity Studio, compile and download to your devices. The example is a very simple one, which only provides the skeleton showing the usage of both NCP host and NCP target. You can verify the example using a smartphone to scan and connect to it. It will advertise after boot or disconnected.

         

        Memory Usage

         

        GBGLib needs RAM for the variables defined in BGLIB_DEFINE(); as well as flash, below is the detailed RAM and flash usage of the example, the compiler is IAR with “High size” optimization.

            Module                 ro code  ro data  rw data

            ------                 -------  -------  -------

        C:\Users\zhfu\SimplicityStudio\v4_mesh_mcu\KBA_ncp_host_pg\IAR ARM - Debug\CMSIS\EFM32PG1B: [1]

            startup_efm32pg1b.o        348

            system_efm32pg1b.o         136       16       16

            ------------------------------------------------

            Total:                     484       16       16

         

        C:\Users\zhfu\SimplicityStudio\v4_mesh_mcu\KBA_ncp_host_pg\IAR ARM - Debug\emlib: [2]

            em_cmu.o                   756        4        4

            em_gpio.o                  156

            em_system.o                 52

            em_usart.o                 340

            ------------------------------------------------

            Total:                   1 304        4        4

         

        C:\Users\zhfu\SimplicityStudio\v4_mesh_mcu\KBA_ncp_host_pg\IAR ARM - Debug\src: [3]

            app.o                      400       20    8 348

            gecko_bglib.o              336

            main.o                     116

            ------------------------------------------------

        Total:                     852       20    8 348

         

        RAM

        The RAM usage for the unit gecko_cmd_packet is 0x104. For 32-bit MCU, each point occupies 4-byte. The length of the queue is 30, so it takes 0x104 * 30 = 0x1e78.

        Total = 0x104 * 2 + 0x4 * 7 + 0x1e78 = 0x209c = 8348 bytes

         

        Flash

        The total flash of the example is 484+1304+852= 2640 bytes. They can be split by functionalities.

        • Basic part - It is required for any EFM32PG1 projects. startup_efm32pg1b.o, system_efm32pg1b.o and main.o and em_system.o, the flash occupation is 484+116+52 = 652 bytes. This part is platform-specific.
        • UART related part -  Driver of UART. em_cmu.o, em_gpio.o and em_usart.o, the flash occupation is 756+156+340 = 1252 bytes. This part is platform-specific.
        • BGLib and application part – App.o has the basic skeleton of the Bluetooth event handler, which is the minimal requirement of application. The flash occupation is 400+336 = 736 bytes.
      • How to find the Bluetooth 5 feature status of a listed device

        Kevin_Fu | 01/15/2018 | 11:47 PM

        There are many new features introduced in Bluetooth 5.0 specification, including 2M PHY, LE coded PHY etc., but they are probably not supported by the devices which were already in the market before Bluetooth 5.0 specification was released. It becomes more important to know which features are supported by specified devices when designing peripherals connecting to them. Here is a description how to get such information from the Bluetooth SIG website.

         

        Below is an example to get the listing information of Samsung Galaxy S8+, the model name is SM-G9550. You can search for any other listed devices following the steps below.

        • Open below link of Bluetooth SIG.

        https://launchstudio.bluetooth.com/listings/search

        • Type the model name into the search label, then click search. If the device is listed in Bluetooth SIG, the report including some major information (such as specification name) should be displayed.

        • Click the Declaration ID. Declaration details will show on the page.

        • Click “View ISC details”.

        • You will see below information on the page. The left part shows all the categories, and the right part shows all the items included in the selected category. Below picture is an example to search “LE 2M PHY” and “LE Coded PHY”, we can see that the LE 2M PHY is supported but the LE Coded PHY is not.

         

        Besides of LE 2M PHY and LE Coded PHY, you can easily find other Bluetooth features on this page and see if they are supported or not.

      • BLE主设备以及GATT客户端例程(连接安卓手机)

        Kevin_Fu | 01/08/2018 | 11:09 PM

        简介

         

        这篇文章是针对只拥有一块开发板同时想实现BLE主设备的人群。如果你有两块或以上的开发板,你可以参考SPP-over-BLE例程,其实现了主从设备两个角色,下面是链接:

         

        如果你只有一块WSTK,你可以使用智能手机作为BLE从设备,然后在WSTK端实现主设备以及GATT客户端相关功能。

         

        典型的连接过程以及连接后GATT相关操作如下:

        1. 主设备扫描附近的广播,你可以加入广播过滤逻辑来确定哪个或者哪些广播的设备是你需要连接的,如过滤设备名称、服务UUID等。
        2. 如果找到设备,建立连接。
        3. 连接之后,扫描远端设备所支持的所有服务以及特征值。
        4. 对于具有通知(notify)或者指示(indicate)的特征值,如果有需要,配置Cline Characteristic Configuration(CCC)的值,其含义如下。
        • 0x0000 – 禁止
        • 0x0001 – 使能通知
        • 0x0002 – 使能指示

        如上步骤和操作是连接以及连接后的典型动作,但并非所有都是必须的。

         

        如何使用这个例程

         

        你需要如下设备

        • 一个EFR32BG或者EFR32MG开发板 – 本例程是直接基于BRD4104A Rev A00(EFR32BG13 radio board)开发的,但他可以很简单的移植到其他开发板或客户的板子。
        • 一个安卓智能手机 – 请确保此智能手机在硬件和软件上都支持BLE,安卓从4.3版本开始在软件上支持BLE。
        •  

        我加入了一个叫做“Demo service”的服务到GATT服务器,其包含了2个特征值,分别叫“NOTIFY_CHAR”和“RW_CHAR”,具体信息如下:

         

                                      UUID                              属性

        Demo Service    df6a8b89-32d1-486d-943a-1a1f6b0b52ed

         

        NOTIFY_CHAR     0ced7930-b31f-457d-a6a2-b3db9b03e39a            通知

        RW_CAHR         fb958909-f26e-43a9-927c-7e17d8fb2d8d           读、写

         

        我将源代码附在了文件末尾,其基于BRD4104A Rev A00(EFR32BG12 radio board)和Bluetooth SDK 2.7.0开发的,同时安卓的APP安装文件也附上了。遵循如下步骤来让例程跑起来。

        1. 将工程导入Simplicity Studio v4中,编译并将工程下载至开发板。工程使用了VCOM来获得串口打印信息,串口打印信息会通过母板的USB口输出。
        2. 你也可以跳过第一步,直接将“ KBA_central_client.hex”文件烧录至开发板,并将apk文件安装至安卓手机。
        3. 打开串口工具来查看打印信息,打开app,手机和开发板会自动建立连接,并使能通知,手机会定时发送通知给开发板。
        4. 按PB0会将0x01和0x05来回地写入RW_CHAR特征值中,这个特征值的值决定了发送通知的周期。例如:特征值的值是5,那么手机会每隔5秒钟发送一次通知。

        下面是手机以及串口工具的截图:

        图1. 串口打印信息

        图2. 手机app截屏

         

        安卓APP

        我的专长并不是安卓开发,所以写这个app仅仅是为了配合WSTK主设备例程来进行演示。我并没有花很多时间来测试这个app的稳定性以及兼容性等,如果你有任何APP相关疑问,你需要找安卓开发工程师来寻求帮助。

        测试过的设备:

        型号                               安卓版本

        三星 Galaxy Tab S3                  7.0

        魅族 MX_4                           5.1

         

        一个已知的问题:

        ·         CCC descriptor – CCC descriptor has the UUID 0x2902, but Android doesn’t support 16-bit UUID, so it needs to be change to 128-bit UUID - 00002902-0000-1000-8000-00805f9b34fb. The API gecko_cmd_gatt_set_characteristic_notification will return error that it can’t find CCC descriptor with UUID 0x2902 in the characteristic. So, I write the next handle of NOTIFY_CHAR which is the location of CCC descriptor of this characteristic on the server side as workaround. This problem didn’t happen when I tested with Android 7.0 devices.

         

         安卓APP的源代码可以在这里下载 - https://github.com/fuzhen011/Android-Peripheral

      • BLE Central and GATT client example - working with an Android app as the peripheral

        Kevin_Fu | 01/08/2018 | 10:56 PM

        Introduction

         

        This article is for people who only have one WSTK and want to implement central role on it. If you have more than one WSTK, you could probably go through the SPP-over-BLE example which implements both the central and peripheral roles.

         

        In case you only have one WSTK, we could use the smartphone as the peripheral and GATT server, then implement the central role and GATT client on the WSTK.

         

        The typical connection process and GATT operations after connection are shown as below:

        1. Scanning for nearby advertisements, you could add your own filter on the advertisement or scan response to make decision which device the central device should connect to.
        2. After filtered device is found, establish connection.
        3. After connection established, discover all services and characteristics.
        4. Configure Client Characteristic Configuration(CCC) for characteristics if needed.

        This is the typical behaviors central device does while connecting to a peripheral, but not all the processes are mandatory.

         

        How to use this example

         

        To run this example, you need to have below devices.

        • An EFR32BG or EFR32MG based board – Although this example was originally developed for BRD4104a Rev A00, on which there is an EFR32BG13 chip, it can be easily migrated to other EFR32 variant based devices.
        • An Android smartphone – Make sure that this device supports BLE both on the hardware and software side, Android has BLE software support from Android 4.3.

         

        GATT Server information, I added a so-called “Demo service” into the server, and this service contains 2 characteristics “NOTIFY_CHAR” and “RW_CAHR”.

         

                                   UUID                                  Properties

        Demo Service     df6a8b89-32d1-486d-943a-1a1f6b0b52ed

        NOTIFY_CHAR      0ced7930-b31f-457d-a6a2-b3db9b03e39a             Notify

        RW_CAHR          fb958909-f26e-43a9-927c-7e17d8fb2d8d         Read and Write

         

        I attached the source code for the central which is based on BRD4104a Rev A00 radio board and Bluetooth SDK 2.7.0, as well as the apk file for Android smartphones. You could follow below steps to use them.

        1. Import the project to your Simplicity Studio, then compile and flash the project to your BRD4104A Rev A00 board. The project enables VCOM to get print information to the USB cable.
        2. Or you can directly flash KBA_central_client.hex file into BRD4104A Rev A00 board, then install the apk file to your Android smartphone.
        3. Open a serial terminal to get the information of central side, open the app from smartphone. They will connect automatically and enable notification and send notification periodically.
        4. Press PB0 on the WSTK will write 0x01 or 0x05 to RW_CHAR back and forth, the notification interval depends on the value of RW_CHAR, for example, if the value is 5, then the notification interval is 5 seconds. Pressing PB1 will read back the value of RW_CHAR.

        Below are screenshots of the serial terminal and smartphone.

        Figure 1. Serial terminal print information

         

        Figure 2. Smartphone screenshot

         

        Android App

        My expertise is not on Android side, I just wanted to develop a simple app which can help to demonstrate the central implementation on EFR32 chipset. I won’t spend a lot of time to test on the Android side, so if there are problems with the app, maybe you could ask Android develop engineer for help.

         

        Tested devices are shown below

        Model                                   Android version

        Samsung Galaxy Tab S3                        7.0

        MEIZU MX_4                                   5.1

         

        One known issue

         

        • CCC descriptor – CCC descriptor has the UUID 0x2902, but Android doesn’t support 16-bit UUID, so it needs to be change to 128-bit UUID - 00002902-0000-1000-8000-00805f9b34fb. The API gecko_cmd_gatt_set_characteristic_notification will return error that it can’t find CCC descriptor with UUID 0x2902 in the characteristic. So, I write the next handle of NOTIFY_CHAR which is the location of CCC descriptor of this characteristic on the server side as workaround. This problem didn’t happen when I tested with Android 7.0 devices. 

         

        Android app source code is available from GitHub - https://github.com/fuzhen011/Android-Peripheral

      • OOB introduction and example

        Kevin_Fu | 01/08/2018 | 09:31 PM

        Introduction of OOB

         

        Below is the description of Out of Band from BLUETOOTH SPECIFICATION Version 5.0 | Vol 1, Part A, 5.2.4.3

        The Out of Band (OOB) association model is primarily designed for scenarios where an Out of Band mechanism is used to both discover the devices as well as to exchange or transfer cryptographic numbers used in the pairing process. In order to be effective from a security point of view, the Out of Band channel should provide different properties in terms of security compared to the Bluetooth radio channel. The Out of Band channel should be resistant to MITM attacks. If it is not, security may be compromised during authentication.


        The user's experience differs a bit depending on the Out of Band mechanism. As an example, with a Near Field Communication (NFC) solution, the user(s) will initially touch the two devices together, and is given the option to pair the first device with the other device. If "yes" is entered, the pairing is successful. This is a single touch experience where the exchanged information is used in both devices. The information exchanged includes discovery information (such as the Bluetooth Device Address) as well as cryptographic information. One of the devices will use a Bluetooth Device Address to establish a connection with the other device. The rest of the exchanged information is used during authentication.


        The OOB mechanism may be implemented as either read only or read/write. If one side is read only, a one-way authentication is performed. If both sides are read/write, a two-way authentication is performed.


        The OOB protocol is selected only when the pairing process has been activated by previous OOB exchange of information and one (or both) of the device(s) gives OOB as the IO capabilities. The protocol uses the information which has been exchanged and simply asks the user to confirm connection.


        The OOB association model supports any OOB mechanism where cryptographic information and the Bluetooth Device Address can be exchanged. The OOB association model does not support a solution where the user has activated a Bluetooth connection and would like to use OOB for authentication only.

         

        Environments

         

        • IDE – Simplicity Studio 4
        • Software – Bluetooth SDK 2.7.0
        • Hardware – BRD4104a Rev A00 * 2
        • Tools – Serial terminal
          • Baud rate: 115200
          • Data bits: 8
          • Stop bit: 1
          • Flow control: False

         

        Purpose of the example

         

        There are 2 OOB pairing modes, one is OOB with legacy pairing and the other is OOB with secure connection pairing. This example implements both modes for user’s reference.

        There are 2 projects in the example, implementing the central and peripheral rolls.

        Central

        • It’s the master roll of the connection
        • Implements the GATT client
        • It sends the write request to the server every 3 seconds and receives the notification from server side.

        Peripheral

        • It’s the slave roll of the connection
        • Implements the GATT server, there are 1 service containing 2 characteristics
          • Notification characteristic – the property of this characteristic is “notify”, which doesn’t require authentication.
          • Write characteristic – the property of this characteristic is “Authenticated write”, which requires authenticated connection to write value to this characteristic.
        • It sends notification to the client every 3 seconds and receives write request from the client.

         

        Due to the different property of these two characteristics, if the pairing and bonding procedure succeeds, the client will receive notifications and the server will receive write requests. Otherwise if pairing and bonding procedure fails, the client should not be able to write the characteristic value due to unauthenticated connection, but it should be able to receive notifications because it doesn’t require authentication.

         

        Key points of the example

         

        • Pairing modes

        In both projects, there is a symbol definition - PAIRING_MODE, it can either be LEGACY_PAIRING or SECURE_CONNECTION_PAIRING. This symbol determines which pairing mode will be used in the connection.

        #define LEGACY_PAIRING                                       1
        #define SECURE_CONNECTION_PAIRING                            2
        
        #define PAIRING_MODE                                         SECURE_CONNECTION_PAIRING
        • Behaviors of both roll
          • Central – It scans for the advertisement containing the service UUID “4880c12c-fdcb-4077-8920-a150d7f9b907”, and establish connection if found. After connection, go through the pairing and bonding procedure, discover services and characteristics. Send write request to the peer device every 3 seconds after the specified characteristic is found. Enable CCC of the specified characteristic the peer device to enable notifications.
          • Peripheral – It won’t start advertising after boot until it receives the OOB data from the serial terminal. For OOB with legacy pairing, the OOB data is 16-byte length, for OOB with secure connection pairing, the length is 32-byte, containing 16-byte OOB data and 16-byte confirm value. It will go through the pairing and bonding procedure after connection established with the central device, and send notifications to central every 3 seconds after CCC is enabled by the central device.

         

        Test the example

         

        As shown above, the example requires 2 devices (BRD4104a Rev A00) and serial terminal, VCOM has been enabled in the example, so the serial print information will go out from the USB cable.

        Central device (#D1) – the device programmed with the project “KBA_oob_central”.

        Peripheral device (#D2) - the device programmed with the project “KBA_oob_peripheral”.

        Serial terminal (#S1) connected to central device.

        Serial terminal (#S2) connected to peripheral device.

         

        Test process

        • Power on both devices (#D1 and #D2) by the USB cable.
        • Open the serial terminals connected to both device, the port name should be “JLink CDC UART Port (COMxx)”.
        • Recognize which serial terminal connects to #D1 and which connects to #D2 by the print information after boot. Enter the right OOB data shown on #S1 to #S2. #D2 should start advertising if it receives enough length of data.
        • #D1 will connect and start pairing and bonding to #D2 automatically.
        • Below are 4 different test results
          • Figure 1 shows what happened if right OOB data was input while using the legacy pairing mode. Both sides can receive the GATT data from the remote peer device.
          • Figure 2 shows what happened if wrong OOB data was input while using the legacy pairing mode. Only the notification can be received, the write characteristic can’t be written because of unauthenticated connection.
          • Figure 3 shows what happened if right OOB data was input while using the secure connection pairing mode. Both sides can receive the GATT data from the remote peer device.
          • Figure 2 shows what happened if wrong OOB data was input while using the secure connection pairing mode. Only the notification can be received, the write characteristic can’t be written because of unauthenticated connection.

         

        Figure 1. OOB with legacy pairing succeed

        Figure 2. OOB with legacy pairing failed

        Figure 3. OOB with Secure Connection pairing succeed

        Figure 4. OOB with Secure Connection pairing failed

      • Different characteristic value types

        Kevin_Fu | 01/04/2018 | 11:05 PM

        This article is about the differences among the types of a characteristic value. In the profile toolkit, there are 3 types of value can be used, hex, utf-8 and user. You can find detailed description in UG118, chapter 2.5.3.

         

        Values:
        hex: Value type is hex
        utf-8: Value is a string
        user: When the characteristic type is marked as type="user" the application is responsible of initializing the characteristic value and also providing it for example when read operation occurs. The Bluetooth stack does not initialize the value, nor automatically provide the value when it's being read. When this is set the Bluetooth stack generates gatt_server_user_read_request or gatt_server_user_write_request which must be handled by the application.
        Default: utf-8

         

        Introduction

         

        The idea of this article is to give both examples of type "user" and "hex" to help users choosing the right property of a characteristic value.

        The most significant difference between the type “user” and the other two types is where the data is stored.

        • Type – user

        If you use "user" as the data type, the value of the characteristic is stored in the application layer. And you need to respond to write/read requests by sending write/read response back via API gecko_cmd_gatt_server_send_user_read_response(…) and gecko_cmd_gatt_server_send_user_write_response(…).

        For example, there is a characteristic with length 20, you need to allocate a 20-byte buffer in the application layer to store its value.

        • When read request received, gecko_evt_gatt_server_user_read_request_id event is generated, you should respond the buffer value via gecko_cmd_gatt_server_send_user_read_response(…)
        • When write request received, gecko_evt_gatt_server_user_write_request_id event is generated, you should modify the local buffer with the data in write request and respond it via gecko_cmd_gatt_server_send_user_write_response(…)

         

        • Type – hex or utf-8

          If you use the property other than "user", the stack will allocate and manage the buffer for the characteristic value automatically.
          • When read request received, the read response will be filled with the characteristic value and sent back to the peer device all by the stack.
          • When received write request, the stack will modify the characteristic value and generate a gecko_evt_gatt_server_attribute_value_id  event to notify the user.
          • If you want to read or write the characteristic value locally, use these 2 APIs gecko_cmd_gatt_server_read_attribute_value(...) and gecko_cmd_gatt_server_write_attribute_value(...). 

         

        2 Notes: 

        1. DO NOT use the APIs gecko_cmd_gatt_server_read_attribute_value(...) and gecko_cmd_gatt_server_write_attribute_value(...) to read or write a characteristic value whose type is "user", because the data buffer is in your application code and stack never knows its value.
        2. DO NOT forget to respond to the read and write requests if the characteristic value type is “user”, otherwise no other GATT operation can be issued until GATT timeout.

         

        Example

         

        IDE – Simplicity Studio 4

        Software -  Bluetooth SDK v2.7.0

        Hardware – BRD4104a Rev A00

         

        1. Create “SoC-Empty” example and specify the project name and compiler (GCC or IAR).

        2. Open the .isc file in the project, modify the GATT database.

        In this example, one service and two characteristics are added into the GATT database.

        • User type characteristic – the value type is “user”, its properties are “read” and “write”
        • Hex type characteristic – the value type is “hex”, its properties are “read” and “write”
        • Because the type “utf-8” has the same operation procedure as “hex”, there is no other characteristic with “utf-8” type.

        Note: DO NOT FORGET TO CLICK “GENERATE” BUTTON AFTER YOU MODIFY THE FILE.

        3. Add below code to the switch block.

        ...
        
        			case gecko_evt_gatt_server_attribute_value_id:
        				// When writing to gattdb_hex_type characteristic, this event is generated to inform the user.
        			break;
        
        			case gecko_evt_gatt_server_user_read_request_id:
        				/* Handle read request to gattdb_user_type characteristic here */
        				if (evt->data.evt_gatt_server_user_read_request.characteristic == gattdb_user_type) {
        					gecko_cmd_gatt_server_send_user_read_response(evt->data.evt_gatt_server_user_read_request.connection, evt->data.evt_gatt_server_user_read_request.characteristic, bg_err_success, sizeof(user_char_buf), user_char_buf);
        				} else {
        					gecko_cmd_gatt_server_send_user_read_response(evt->data.evt_gatt_server_user_read_request.connection, evt->data.evt_gatt_server_user_read_request.characteristic, (uint8) bg_err_att_invalid_handle, 0, NULL);
        				}
        			break;
        
        			case gecko_evt_gatt_server_user_write_request_id:
        				/* Handle write request to gattdb_user_type characteristic here */
        				if (evt->data.evt_gatt_server_user_write_request.characteristic == gattdb_user_type) {
        					if (evt->data.evt_gatt_server_user_write_request.offset + evt->data.evt_gatt_server_user_write_request.value.len <= sizeof(user_char_buf)) {
        						memcpy(user_char_buf + evt->data.evt_gatt_server_user_write_request.offset, evt->data.evt_gatt_server_user_write_request.value.data, evt->data.evt_gatt_server_user_write_request.value.len);
        						gecko_cmd_gatt_server_send_user_write_response(evt->data.evt_gatt_server_user_write_request.connection, evt->data.evt_gatt_server_user_write_request.characteristic, bg_err_success);
        					} else {
        						gecko_cmd_gatt_server_send_user_write_response(evt->data.evt_gatt_server_user_write_request.connection, evt->data.evt_gatt_server_user_write_request.characteristic, (uint8) bg_err_att_invalid_att_length);
        					}
        				} else if (evt->data.evt_gatt_server_user_write_request.characteristic == gattdb_ota_control) {
        					/* Set flag to enter to OTA mode */
        					boot_to_dfu = 1;
        					/* Send response to Write Request */
        					gecko_cmd_gatt_server_send_user_write_response(evt->data.evt_gatt_server_user_write_request.connection,
        					gattdb_ota_control, bg_err_success);
        
        					/* Close connection to enter to DFU OTA mode */
        					gecko_cmd_endpoint_close(evt->data.evt_gatt_server_user_write_request.connection);
        				} else {
        					gecko_cmd_gatt_server_send_user_write_response(evt->data.evt_gatt_server_user_write_request.connection, evt->data.evt_gatt_server_user_write_request.characteristic, (uint8) bg_err_att_invalid_handle);
        				}
        			break;
        
        ...

         

         

        Test the example

         

        The example code shows where to handle the read and write requests to the characteristic with user type, as well as the event generated by write request to the characteristic with hex/utf-8 type.

        Follow below steps to test the example:

        • Import the attached project to your Simplicity Studio 4
        • Build and program the project to the specified board
        • Use Blue Gecko app to connect
        • Try to read and write the 2 characteristics and think why the initial value of these 2 characteristics are different, where the initial value is set?

         

        When to use "user" and when to use "hex"?

         

        • Type hex/utf-8
          • Advantage – Stack will handle the read and write request to the characteristics
          • Disadvantage – User has to use BlueGecko APIs to read and write the value locally
        • Type user
          • Advantage – The buffer storing the characteristic value is in the application layer, it’s easier to read and modify the value.
          • Disadvantage – User must respond to the read and write requests by calling BlueGecko APIs. If user doesn’t do it, no other GATT operation can be issued until GATT timeout.
      • 低功耗蓝牙安全性 - Simplicity Studio例程

        Kevin_Fu | 01/04/2018 | 01:51 AM

        这篇文章的英文原版可以从下面链接找到,因为其比较有用,所以我把它翻译成中文来方便中国客户阅读。感谢原作者Balazs Adamffy.

        https://www.silabs.com/community/wireless/bluetooth/knowledge-base.entry.html/2016/06/13/bluetooth_smart_secu-BpM6

         

        简介

         

        这篇文章将会介绍在Simplicity Studio 4以及Bluetooth SDK v2.7.0下, 如何使用低功耗蓝牙(BLE)的安全相关特性,其包括配对、绑定、加密和授权。

        首先,我们给出一些关于BLE安全性的一些基础信息,然后突出介绍附件的例程里的重要的代码片段。示例程序实现了一个加密传输,其特征值只能在配对和绑定完成才能被读出。

        软硬件信息:

        Bluetooth SDK版本 – 2.7.0

        开发板 – EFR32BG13开发板brd4104a Rev A00

         

        BLE安全性特征

         

        最常见的无线通讯的威胁如下:

        • 被动监听(Passive eavesdropping)
        • 主动监听(Active eavesdropping = Man-in-the-Middle (MITM))
        • 隐私(Tracking)

        BLE定义了5种安全特性来对抗上述威胁:

        • 配对(Pairing) - 设备间建立可信的连接(密钥(Key)的产生、交换,以及ID信息的交换)
        • 绑定(Bonding) - 保存配对阶段所产生的Key
        • 设备身份认证(Device authentication) - 验证两个设备具有相同的Keys(防护MITM)
        • 加密(Encryption) - 数据加密(FIPS、NIST、AES128-CCM)
        • 数据签名(Data signing,信息一致性) - 防止数据被修改

        上述特征实现在BLE协议栈的不同层,参下图:

         

        配对&绑定

         

        配对

        • 配对是一个建立可信连接的过程
        • 用于产生和交换密钥(Security Keys)
        • 用于交换ID信息

        BLE使用Secure Simple Pairing(SSP)配对模型:

        • Just works - 针对于没有交互界面的设备,无需用户操作,其无法提供MITM防护
        • Passkey entry - 用户需输入另一设备的显示屏所显示的passkey, 其提供MITM防护
        • Numeric comparison - 用户需要确认双方显示屏所显示的passkeys。其提供MITM防护。注意:此方法在Blue Gecko的协议栈下还尚未支持
        • Out-of-band - 用其他技术交换keys,比如NFC

         

        绑定

        • 保存keys以备之后使用
        • 用于鉴别连接、验证设备ID等

         

        隐私

         

        • BLE提供隐私保护
        • 设备可以使用公共地址或者私有(随机)地址
          • 对于一个设备,其公共地址是固定且唯一的
          • 随机地址可以随时间改变而改变,其可以对不想建立连接的设备隐藏其公共地址
          • 绑定设备可以通过key来解析设备的公共地址

        注意:随机地址尚未在Blue Gecko的协议中实现。

         

         加密

         

        •  加密过程用于保证数据的完整性和一致性
        • 已配对或绑定的设备可以加密/解密连接中的数据
        • BLE使用AES-128作为加密算法

        注意:广播数据不支持加密

         

         

        蓝牙4.2新加入的安全特性

         

        • LE Secure connections - 将Key的交换机制升级至更安全的配对流程 - ECDH
        • LE privacy 1.2 - ID信息解析由HOST层转移到Controller层,这样提升了速度并减小了功耗

         

        示例程序

         

        此示例程序的软硬件基础在上面已经提到,同时只需要做很少的改动,它便可以用于其他开发板,如BGM111/BGM113等。

         

        示例程序实现了一个服务及一个特征值,其被另外设备读的前提是双方配对并绑定, 以下是完成这一任务的具体步骤:

         

        1. 建立SoC-Empty工程,并指定其工程名称选择编译器(GCC或IAR)

         

        2. 打开工程中的.isc文件,加入一个服务和一个特征值

        Security的服务和一个叫My Secret的特征值。 因为authenticated_read属性被设为“true”,所以其只有在加密连接中才能被读出。

        注意:不要忘记修改完之后,点击右上角的“Generate”按钮。

         

        3. 使能VCOM获得串口打印

        • 打开工程根目录下的hal-config.h文件,做如下修改
        #define HAL_VCOM_ENABLE                   (1)
        • 打开目录C:\SiliconLabs\SimplicityStudio\v4\developer\sdks\gecko_sdk_suite\v2.1\hardware\kit\common\drivers,将<retargetio.c><retargetserial.c><retargetserial.h>拖入工程,如下图

        • 在main.c中加入头文件引用以及串口初始化函数
        ...
        
        #include "retargetserial.h"
        #include "stdio.h"
        
        ...
        
        void main(void)
        {
          // Initialize device
          initMcu();
          // Initialize board
          initBoard();
          // Initialize application
          initApp();
        
          // Initialize stack
          gecko_init(&config);
        
          RETARGET_SerialInit();
        
          while (1) {
        
        ...
        

        完成如上修改后,即可使用printf()函数来获得串口打印数据了。

         

        4. 配置、使能配对和绑定

        • gecko_cmd_sm_set_bondable_mode(1)来使能绑定。
        • gecko_cmd_sm_configure(flags, io_capabilities)来完成安全相关配置。

        flag参数的bit 0:

        • 允许不带MITM保护的绑定
        • 绑定需带有MITM保护

        flag参数的bit 1:

        • 允许不绑定直接加密数据
        • 加密数据必须先绑定

        flag参数的bit 2:

        • 允许在legacy配对情况下绑定
        • 仅允许Secure connections

        flag参数的bit 3:

        • 绑定请求不需要确认
        • 绑定请求需要被确认,当收到绑定请求时产生sm_confirm_bonding事件

        flag的4 - 7位保留,应设为0

        capabilities 参数指示设备支持的输入输出类型,不同的capabilities 参数会导致不同的配对方法。

        系统启动后,调用函数gecko_cmd_sm_configure

        当使用sm_io_capability_displayonlysm_io_capability_displayyesno作为io capabilities时,PIN码会显示在UART控制台,你需要在手机或平板端输入这个PIN码。

        当使用sm_io_capability_keyboardonlysm_io_capability_keyboarddisplay作为io capabilities时,PIN码会显示在手机或平板端,你需要在设备的UART控制台输入这个PIN码。

        不要使用sm_io_capability_noinputnooutput,因为MITM保护不能在此模式下工作,配对和绑定将会失败。

        ...
        
              case gecko_evt_system_boot_id:
        
              	printf("Boot\r\n");
        
              	/* Set the pairing configuration */
              	gecko_cmd_sm_configure(0x0F, sm_io_capability_displayonly);
        
              	/* Enable bonding */
              	gecko_cmd_sm_set_bondable_mode(1);
        
        ...
        

         

        5. 加入配对绑定相关的事件处理

        代码如下

        ...
        
        case gecko_evt_sm_confirm_bonding_id:
              	gecko_cmd_sm_bonding_confirm(evt->data.evt_sm_confirm_bonding.connection, 1);
              	printf("Bonding confirmed\r\n");
              	break;
        
              case gecko_evt_sm_bonded_id:
              	printf("Bondind completed\r\n");
              	break;
        
              case gecko_evt_sm_bonding_failed_id:
              	printf("Bondind failed, reason = 0x%04x\r\n", evt->data.evt_sm_bonding_failed.reason);
              	break;
        
              case gecko_evt_sm_passkey_display_id:
              	printf("Passkey = %06d\r\n", evt->data.evt_sm_passkey_display.passkey);
              	break;
        
        ...

         

        测试此例程

        下载Blue Gecko app:

        iOS用户可以通过App Store,安卓用户可以通过Google Play获得。同时可以通过Silicon Labs的官方网站获得。安卓用户点击此处,iOS用户点击此处

         

        完成如下步骤:

        1. 将此例程烧录至WSTK。
        2. 删除手机或平板端关于此设备的绑定信息。
        3. 打开串口中断,COM口选择 J-LINK CDC UART.
        4. 打开Blue Gecko app并选择Bluetooth Brower
        5. 连接设备至手机或平板。
        6. 当程序要读取My Secret特征值的时候,系统会开始配对和绑定的流程,串口会显示passkey,需要在手机端输入同样的passkey完成配对绑定才能够读取出此特征值的值。

           7.如果一切正常,你可以通过APP读取GATT的特征值,并在串口终端得到Bonding completed信息。删除手机端绑定再次        连接可以进行重复测试

      • 在蓝牙工程中使用Gecko bootloader

        Kevin_Fu | 01/03/2018 | 10:09 PM

        这篇文章的英文原版可以从下面链接找到,因为其比较有用,所以我把它翻译成中文来方便中国客户阅读。感谢原作者Arnold Kalvach.

        https://www.silabs.com/community/wireless/bluetooth/knowledge-base.entry.html/2017/04/12/adding_gecko_bootloa-osqt

         

        从蓝牙2.3.0的SDK开始,我们加入了Gecko bootloader的支持,但他并不是默认加入到工程中的,从2.7.0的SDK开始,我们全面的摒弃了legacy bootloader的使用。所以每一个蓝牙的工程都需要烧录一个Gecko bootloader。

        • 对于EFR32xG1系列的设备,其存放的起始地址是0x0000
        • 对于EFR32xG12和EFR32xG13系列的设备,其存放在一块特定的地址区域,并不占用内部Flash空间,应用的起始地址是0x0000.

        如果你想要将Gecko bootloader加入到工程中去,可以有如下方法。

         

        第一种

        1. 编译你的蓝牙工程。

        2. 将其烧录至设备

        3. 建立一个新的Gecko bootloader的工程,例如:BGAPI UART DFU Bootloader(点击“New project”按钮,然后选择“Gecko BootLoader”, 然后选择你需要的bootloader)

        4. 点击"Generate"并编译

        5. 烧录以"-combined.s37"结尾的文件至设备,也可以交换顺序,先烧录Gecko bootloader再烧录用户蓝牙工程。

         

        第二种

        1. 编译你的蓝牙工程。

        2. 建立一个新的Gecko bootloader的工程,例如:BGAPI UART DFU Bootloader

        3. 点击"Generate"并编译

        4. 合并bootloader和应用,在命令行输入:

            commander convert bootloader-uart-bgapi-combined.s37 your_application.s37 -o app+bootloader.s37

        5. 将合并的文件烧录至设备。

         

        注意:如果你没有修改安装目录,commander.exe在C:\SiliconLabs\SimplicityStudio\v4\developer\adapter_packs\commander\目录下可以找到。GCC 是在2.4.0的SDK开始才全面支持的,2.3.x的SDK对于GCC的支持仅仅是测试阶段。

      • BLE + Micrium RTOS for EFR32xG1 devices

        bluetoothsteve | 01/02/2018 | 10:52 AM

        Starting in Silicon Labs Bluetooth SDK 2.6.0, a sample application has been available to demonstrate how to get started with running a Bluetooth application on top of the Micrium RTOS. Currently the sample applications in the SDK are only available for the EFR32xG12 and EFR32xG13 SoCs and modules. Improvements have now been made to allow this sample application to run on the EFR32xG1 SoCs and modules. The EFR32xG1 version of the application will be made part of future release of our SDK, until that happens you can request a  copy of that sample application  built for v2.7.x of our SDK : one for IAR and one for GCC by requesting through a support ticket here https://siliconlabs.force.com/home/home.jsp. Please see application note AN1114 for a walkthrough of this sample application.