SPP-over-BLE C example for BGMxxx

by <a href="http://community.silabs.com/t5/Welcome-and-Announcements/Community-Ranking-System-and-Recognition-Program/m-p/140490#U140490"><font color="#000000"><font size="2">Legend Employee</font></font> </a> JaakkoV ‎04-13-2017 09:14 AM - edited ‎04-26-2017 05:10 AM

Introduction

 

This example shows how to implement transparent serial data connection between two BGMxxx modules. Functionally the example is very close to the BGScript example that is described in following article:

http://community.silabs.com/t5/Bluetooth-Wi-Fi-Knowledge-Base/SPP-over-BLE-BGScript-example-for-BGM1...

 

There is no standard SPP service in Bluetooth Smart and therefore we need to implement this as a custom service. The service is exactly same as the one used in the BGScript example (see link above) and it can be described using the XML notation as follows:

 

 

	<!-- Our custom accelerometer service is declared here -->	 
	<!-- UUID values generated with https://www.guidgenerator.com/ --> 
	<service uuid="4880c12c-fdcb-4077-8920-a450d7f9b907" advertise="true">
        <description>SPP Service</description>
        
		<characteristic uuid="fec26ec4-6d71-4442-9f81-55bc21d658d6" id="xgatt_spp_data">
            <description>SPP Data</description>
            <properties write_no_response="true" notify="true" />
			<value variable_length="true" length="20" type="hex"></value>
		</characteristic>
    </service>

 

The basic idea of the SPP service is explained in the BGScript article linked above and therefore it is not covered here.

 

The zip file attached at the end of this article includes source code for one single application that implements both the server and client roles. The role is selected dynamically at power-up using pushbuttons, details are found later in the section Running the demo.  

 

Building the SPP project

 

This example has been tested with Bluetooth SDK 2.3.1 and GCC toolchain. The code should work without any changes at least with the following radio boards:

BGM111 (PCB4300A)
BGM121 (BRD4302A)

 

The zip file attached at the end of this article includes the source files for the C-based SPP example. It is not a complete project but a set of files that you can copy on top of a project created in Simplicity Studio. Follow these step-by-step instructions carefully:

 

Step 1: Create the SOC -Empty example project in Studio

 

After the project is created the BLE GATT Configurator is opened automatically and it shows the GATT database of the project. The project template includes a minimal GATT database that includes three services (Generic Access, Device Information and Silicon Labs OTA). Next you need to add the SPP service using the BLE GATT Configurator.

 

Step 2: add the SPP service

 

The details of the SPP service are:

Service UUID value  4880c12c-fdcb-4077-8920-a450d7f9b907

SPP data : UUID value  fec26ec4-6d71-4442-9f81-55bc21d658d6

 

For the SPP data characteristic, define the ID as “gatt_spp_data”.

The length of the characteristic is set to 20 bytes and type is hex. variable length checkbox selected.

 

Add and enable following properties: write without response and notify.

 

 

The following screenshots show how the SPP service should look like in the BLE GATT Configurator.

 

SPP service:

 

SPP_SERVICE.png

 

SPP_data characteristic:

 

SPP_DATA.png

After adding the service, save the *.isc file and press Generate button on the upper right corner of the GUI.

 

At this point, it is good to check that the project builds without any errors.

 

Step 3: add the C source files to the project

 

Unzip the attached zip file and add the included source files to the project.

 

Files can be added to the project simply by drag&drop. Studio will prompt you to either create a link to these files or create a copy. Select “copy” option. Note that the main.c that was created by Studio as part of the SOC – Empty example is overwritten.

 

Step 4: defined RETARGET_VCOM

 

Finally, in the project settings you need to define the precompiler directive RETARGET_VCOM so that the code uses the on-board USB-to-UART converter of the development kit. 

 

Following screenshot shows how to set this in the GCC build options:

 

RETARGET_VCOM.PNG

 

After building the project, flash the firmware to two development kits. The same application supports both SPP server and client roles. The following section explains how to select the mode.

 

Running the demo

 

Simplest way to run the demo is to use two similar development kits (for example two BGM121 kits). In this case you can use the same binary for both boards.

 

When the application boots, it checks the state of pushbuttons PB0, PB1. If buttons are not pressed the application starts in SPP server role.

 

By keeping either PB0 or PB1 pressed during reboot the application starts in SPP client mode.

 

In server mode, the device advertises the custom SPP service and waits for incoming connections.

 

In client mode, the device starts scanning and searches for the custom SPP UUID in the scan responses. If match is found, the client connects to the target, discovers the SPP service and characteristics and then enables notifications for the SPP_data characteristic. At this point, any data that is input in the client side is sent over the air to the server and printed on the remote UART. Similarly, any data input to the server UART is transmitted back to the client.

 

To connect to the kit using terminal program use the following UART settings: baud rate 115200 , 8N1, no flow control.

 

The example can be also tested between two different kits (e.g. BGM121 and BGM111). As the SPP service is the same that was used in the BGScript SPP example, it is also possible to connect BGScript-based SPP client to C-based SPP server, or vice versa. 

 

Yet another option is to use BLED112 as the SPP client, see following article for more info:

http://community.silabs.com/t5/Bluetooth-Wi-Fi-Knowledge-Base/SPP-client-example-using-BLED112-dongl...

 

 

Power management

 

USART peripheral is not accessible in EM2 sleep mode. For this reason, both the client and the server applications disable sleeping (EM2 mode) temporarily when the SPP mode is active. SPP mode in this context means that the client and server are connected and that the client has enabled notifications for the SPP_data characteristics.

 

When SPP mode is entered, the code calls SLEEP_SleepBlockBegin(sleepEM2) to temporarily disable sleeping. When connection is closed (or client disables notifications) then SLEEP_SleepBlockEnd(sleepEM2) is called to re-enable sleeping.

 

For more details on the power management details, see following article:

http://community.silabs.com/t5/Bluetooth-Wi-Fi-Knowledge-Base/Using-Energy-Modes-with-Bluetooth-Stac...

 

Known issues

 

The sample code uses printf() for sending data to UART. For this reason, the example does not well with binary data transfer. 

 

Conclusion

 

This example is a simple C-based SPP implementation for BGMxxx / EFR32BG products. It is not optimized for performance or low power. The code has been kept as simple as possible.

 

UART input/output is handled using stdio retarget functions (see following article for details:

http://community.silabs.com/t5/Bluetooth-Wi-Fi-Knowledge-Base/Retarget-stdio-to-UART-in-BLE-SDK-2-0-... )

 

This is not the most efficient way to handle UART input/output but the benefit is that it is portable and allows the sample code to be used easily on several radio boards without any modifications.

 

 

 

Comments
by <a href="http://community.silabs.com/t5/Welcome-and-Announcements/Community-Ranking-System-and-Recognition-Program/m-p/140490#U140490"><font color="#000000"><font size="2">Super Star</font></font> </a> Riscy00
on ‎04-14-2017 05:40 AM

Hi

 

This is what I'm looking for SPP implementation. 

 

Why there is no SPP in Visual GATT for EFR32BG1 with EVAL Startup Board  PCB4100A Rev 3 ?

 

What needed to make SPP work for this EFR32BG1 device?, I do not like package from BGMxxx series.

by <a href="http://community.silabs.com/t5/Welcome-and-Announcements/Community-Ranking-System-and-Recognition-Program/m-p/140490#U140490"><font color="#000000"><font size="2">Legend Employee</font></font> </a> JaakkoV
on ‎04-14-2017 05:51 AM

This SPP implementation is a custom service I made up just for demo purposes. It is not included in the Visual GATT editor at least for now.

 

The example discussed in this article should work also with PCB4100A without any changes. You first need to create the Soc Empty for this specific board and then add the SPP source files as instructed above.

by <a href="http://community.silabs.com/t5/Welcome-and-Announcements/Community-Ranking-System-and-Recognition-Program/m-p/140490#U140490"><font color="#000000"><font size="2">Super Star</font></font> </a> Riscy00
on ‎04-14-2017 09:59 AM

I have written this code into EFR32BG1 via EVAL board PCB4001 (which should be similar to BTExxx device).

 

I cannot see VCOM appearing in device list in Window Laptop not my android phone.

 

I like to make connection over SPP in bluetooth between Window Laptop or Andoid Phone and this device. What need to be done and how?

by MarcinB
on ‎04-18-2017 07:06 AM

You should see device like JLink CDC Uart Driver in Device Manager (COMx), and this is the correct COM device to conect in this example. But this is GATT service not real SPP profile so you will not see any extra COM ports. 

by <a href="http://community.silabs.com/t5/Welcome-and-Announcements/Community-Ranking-System-and-Recognition-Program/m-p/140490#U140490"><font color="#000000"><font size="2">Super Star</font></font> </a> Gio63
on ‎04-20-2017 03:40 AM

Hi

I found C_BASED_SPP_EXAMPLE very useful. I'd like to know which pheripheral must be enabled (RTC must be enabled for example?)because in the zip file there is no InitDevice.c file. 

Best Regards

Giovanni

by <a href="http://community.silabs.com/t5/Welcome-and-Announcements/Community-Ranking-System-and-Recognition-Program/m-p/140490#U140490"><font color="#000000"><font size="2">Legend Employee</font></font> </a> JaakkoV
on ‎04-20-2017 03:51 AM

@Gio63 if you create the Soc Empty example for your target radio board in Studio you will get the InitDevice.c file that is suitable for that board.

 

by <a href="http://community.silabs.com/t5/Welcome-and-Announcements/Community-Ranking-System-and-Recognition-Program/m-p/140490#U140490"><font color="#000000"><font size="2">Super Star</font></font> </a> Gio63
on ‎04-21-2017 02:42 AM

Thank you JaakkoV. Just another question......I need to send data received from SPP client through UART but I need to send binary data as well so I think printf can't work. I thought to modify file spp_server_main.c (inside C_BASED_SPP_EXAMPLE) because my application behave only as a server in this way:

 

  switch (BGLIB_MSG_ID(evt->header)) {

                 .....

                ........

                  ......

                case gecko_evt_gatt_server_attribute_value_id:
               {

                          memcpy(printbuf, evt->data.evt_gatt_server_attribute_value.value.data, evt->data.evt_gatt_server_attribute_value.value.len);
                          TxBuf(printfbuf, evt->data.evt_gatt_server_attribute_value.value.len);


               } 

                 ......

 }

 

 int TxBuf(uint8_t *buffer, int nbytes)
{
 int i;

 for (i = 0; i < nbytes; i++)
 {
    RETARGET_WriteChar(*buffer++);
  }
  return nbytes;
}

Do you think could it work? Thank you

Giovanni

 

 

by <a href="http://community.silabs.com/t5/Welcome-and-Announcements/Community-Ranking-System-and-Recognition-Program/m-p/140490#U140490"><font color="#000000"><font size="2">Legend Employee</font></font> </a> JaakkoV
on ‎04-26-2017 05:15 AM

@Gio63 the solution that you proposed looks good to me. You don't necessarily need to use memcpy to first copy the bytes into another buffer. You could simply just have one function call:

 

TxBuf(evt->data.evt_gatt_server_attribute_value.value.data, evt->data.evt_gatt_server_attribute_value.value.len);
by <a href="http://community.silabs.com/t5/Welcome-and-Announcements/Community-Ranking-System-and-Recognition-Program/m-p/140490#U140490"><font color="#000000"><font size="2">Super Star</font></font> </a> Gio63
on ‎04-26-2017 09:07 AM

Thank you Jaakkov. In the file ssp_server_main.c I don't find any call to API Function "gecko_cmd_le_gap_set_adv_parameters" There is any reason ?

Thank you

Best Regards

Giovanni

by <a href="http://community.silabs.com/t5/Welcome-and-Announcements/Community-Ranking-System-and-Recognition-Program/m-p/140490#U140490"><font color="#000000"><font size="2">Legend Employee</font></font> </a> JaakkoV
on ‎04-26-2017 09:16 AM

The example uses default advertising parameters. You can add a call to gecko_cmd_le_gap_set_adv_parameters before starting advertisements if you want to use some other settings.

 

by <a href="http://community.silabs.com/t5/Welcome-and-Announcements/Community-Ranking-System-and-Recognition-Program/m-p/140490#U140490"><font color="#000000"><font size="2">Super Star</font></font> </a> Gio63
on ‎04-27-2017 02:31 AM

Thank you Jaakkov. From the point of view of server side if a server want to close a connection it  need to call  the API function  "gecko_cmd_endpoint_close". Is it correct?

Thank you

Best Regards

Giovanni

 

by <a href="http://community.silabs.com/t5/Welcome-and-Announcements/Community-Ranking-System-and-Recognition-Program/m-p/140490#U140490"><font color="#000000"><font size="2">Legend Employee</font></font> </a> JaakkoV
on ‎04-27-2017 02:34 AM

Yes, endpoint close can be used to close connection either by server or client. 

 

by <a href="http://community.silabs.com/t5/Welcome-and-Announcements/Community-Ranking-System-and-Recognition-Program/m-p/140490#U140490"><font color="#000000"><font size="2">Super Star</font></font> </a> Gio63
on ‎05-08-2017 06:07 AM

Hi 

I have a problem with serial RX Interrupt. After connection with server the rx interrupt of client module has problems. The interrupt dosn't alway trigger. I set a breakpoint in the interrupt routine but the program counter doesn't go there every time a serial character is received from serial line

Do you know the reason ?
Best Regard

Giovanni

by <a href="http://community.silabs.com/t5/Welcome-and-Announcements/Community-Ranking-System-and-Recognition-Program/m-p/140490#U140490"><font color="#000000"><font size="2">Legend Employee</font></font> </a> JaakkoV
on ‎05-08-2017 07:46 AM

@Gio63 no, unfortunately can't tell the reason for that. Is that with the original example code provided in this article or some modified version of yours? In the latter case, I suggest that you start a new topic on the forum and add your code as attachment,

by <a href="http://community.silabs.com/t5/Welcome-and-Announcements/Community-Ranking-System-and-Recognition-Program/m-p/140490#U140490"><font color="#000000"><font size="2">Super Star</font></font> </a> Gio63
on ‎05-08-2017 09:30 AM

Hi

I solved the problem I forgot to call the routine "SLEEP_SleepBlockBegin(sleepEM2)" and I use UART1 so I can't go to EM2. 

I'd like to know if it possible to go into EM1 mode instead of going into EM2 mode when bluetooth is working. In my application I use a small battery so I have to save a lot of energy

Thank you

Giovanni

by <a href="http://community.silabs.com/t5/Welcome-and-Announcements/Community-Ranking-System-and-Recognition-Program/m-p/140490#U140490"><font color="#000000"><font size="2">Legend Employee</font></font> </a> JaakkoV
on ‎05-08-2017 11:07 AM

SLEEP_SleepBlockBegin(sleepEM2) means that the device is not allowed to enter EM2 (or deeper) sleep modes, but it will still enter EM1 whenever possible.

 

If you want to save power, one possibility would be to use a GPIO input to enable/disable sleep whenever needed. Kind of a "wakeup pin", just like the one that is used in NCP mode designs. (See https://www.silabs.com/documents/login/user-guides/UG119-BlueGecko-BT-Device-Config.pdf and section 3.2 <wake_up> for more info).

 

Another possibility could be to use LEUART that is accessible also in EM2.

by <a href="http://community.silabs.com/t5/Welcome-and-Announcements/Community-Ranking-System-and-Recognition-Program/m-p/140490#U140490"><font color="#000000"><font size="2">Super Star</font></font> </a> Gio63
on ‎05-12-2017 07:17 AM

Hi

I can't use LEUART because I need of IRDA interface so I must use UART. I'd like to know if  is present the flags" .sleep.flags=SLEEP_FLAGS_DEEP_SLEEP_ENABLE,2" IN  Gecko configuration parameters  after calling the function SLEEP_SleepBlockBegin(sleepEM2) does the bluetooth protocol enter in EM1 mode?

Thank You

Best Regards

Giovanni

 

 

by <a href="http://community.silabs.com/t5/Welcome-and-Announcements/Community-Ranking-System-and-Recognition-Program/m-p/140490#U140490"><font color="#000000"><font size="2">Legend Employee</font></font> </a> JaakkoV
on ‎05-12-2017 11:09 AM

>> I'd like to know if  is present the flags" .sleep.flags=SLEEP_FLAGS_DEEP_SLEEP_ENABLE," IN  

>> Gecko configuration parameters  after calling the function SLEEP_SleepBlockBegin(sleepEM2)

>> does the bluetooth protocol enter in EM1 mode?

 

Yes, in this case stack enters EM1 whenever possible.

by <a href="http://community.silabs.com/t5/Welcome-and-Announcements/Community-Ranking-System-and-Recognition-Program/m-p/140490#U140490"><font color="#000000"><font size="2">Super Star</font></font> </a> Gio63
on ‎05-13-2017 05:42 AM

Thank you. Yes the flag SLEEP_FLAGS_DEEP_SLEEP_ENABLE is present after callingSLEEP_SleepBlockBegin(sleepEM2) and do I think stacks enter EM1 mode when possible . Another question.....Can I wake up module from EM2 with an input pin for example with UART Serial RX pin? If it possible I could avoid to call SLEEP_sleepBlockBegin function and micro could enter in EM2 mode.

Thank  you

Best Regards

 

Giovanni 

by <a href="http://community.silabs.com/t5/Welcome-and-Announcements/Community-Ranking-System-and-Recognition-Program/m-p/140490#U140490"><font color="#000000"><font size="2">Legend Employee</font></font> </a> JaakkoV
on ‎05-13-2017 06:06 AM

It's not possible to wake up on UART RX pin. You can use a separate wakeup pin but it can't be one of the UART pins.

by <a href="http://community.silabs.com/t5/Welcome-and-Announcements/Community-Ranking-System-and-Recognition-Program/m-p/140490#U140490"><font color="#000000"><font size="2">Super Star</font></font> </a> Claus_HY
on ‎05-19-2017 03:42 AM

after following you instructions I see on terra term as follows:

þDISCONNECTED!connectedConn.parameters: interval 200 units, txsize 27
þDISCONNECTED!connectedConn.parameters: interval 200 units, txsize 27
þDISCONNECTED!s: interval 200 units, txsize 128

and on the other side

Found SPP device
Empty Exconnected
Conn.parameters: interval 200 units, txsize 27
service discovered
Conn.parameters: interval 200 units, txsize 128
SPP char not found?
DISCONNECTED!

this will be repeats more than one time and then it stops.

I used the BGM113.

Maybe some Settings are missed?

I have got no static connection between the modules.

 

thx

 

by <a href="http://community.silabs.com/t5/Welcome-and-Announcements/Community-Ranking-System-and-Recognition-Program/m-p/140490#U140490"><font color="#000000"><font size="2">Legend Employee</font></font> </a> JaakkoV
on ‎05-19-2017 04:25 AM

The connection is dropped by the SPP client because it can't find the SPP_data characteristic in the remote database:

 

SPP char not found?

 

Please check the SPP_data characteristic definition. Possibly a mistake in the UUID value? 

by <a href="http://community.silabs.com/t5/Welcome-and-Announcements/Community-Ranking-System-and-Recognition-Program/m-p/140490#U140490"><font color="#000000"><font size="2">Super Star</font></font> </a> Claus_HY
on ‎05-19-2017 06:47 AM

Copy paste error, now it works..

thx