This blog series was created as an attempt to fill in the gap between how Bluetooth Smart is described in the spec and how you can use our APIs and event from our softdevice to do what defined in the spec.
[UPDATE]We had quite a lot of new features and changes in our newer Softdevice since this blog was written. The information in this blog is only applied for and up to S110 v8.0, S130 v2.0, S132 v2.0.
This is part 2 of the series. You can find other parts here:
Part 1 GAP - Advertising
Table of content
A. Connection establishing and terminating
II. Connection parameters
IV. Connection Terminating
B. When in connection
I. Data channel packet format
II. Acknowledgement and Flow Control
C. Setting up a connection with Nordic Softdevice
I. APIs provided by the softdevice
II. GAP events you may receive when initiate/terminate connection
III. Example code
Basic topology of Bluetooth smart is star topology where one central can connects to several peripherals. A peripheral only connect to one central. Mesh topology will be implemented in the next release of Bluetooth spec. However, by the time of writing this, star topology is the only connection topology of Bluetooth. Note that a master can talk to a BR/EDR (Bluetooth Classic) slave also. But Nordic Softdevice doesn't support BR/EDR.
Recap from part 1: the advertiser broadcasts advertising packets so that scanner and initiator can receive the advertising data or initiate a connection.
A connection is initialized with a CONNECT REQUEST.
A central that wants to start a connection has to scan for an advertising packet and send a connect request packet after it receive the advertising packet from the advertiser it's looking for. The connect request must be sent within the RX windows opened by the advertiser right after each advertising packet transmission [Section 188.8.131.52 Vol1 Part A]. This is shown in the figure bellow.
When the advertiser receives a connect request and if the connection request is accepted, the advertiser should stop advertising in the next channel and/or next advertising interval then follow the parameter in the connect request packet to start a connection. The advertiser accepts a connect request when it is advertising in connectable mode and with one of following cases:
The following figure shows an example when an advertiser receive a connect request on channel 38 . It stops advertising when receives the packet, and a connection is established with the parameter included in the connect request. We will discuss these parameters in the next section.
The first connection packet (connect event) should happen inside a transmit window defined by the transmit window size and the transmit window offset[4.5.3 Vol6 PartB]. After that the Advertiser becomes Slave and the Initiator becomes Master. The master will keep sending connection event packet on every connection interval and the Slave in accordance will open the RX windows on every connection interval after the first connection event, and then send a connection event packet back to the master on each connection event. This connection event packet act as an ACK. It can contain data payload or not.
Note that the master has no way to know if the connect request is accepted by the advertiser or not, so it will assume that the connection is accepted and keep sending connection event packet, in our case it will keep sending 6 packets (6 connection events) and stop if there is an connect event packet back from the slave to ACK. Same with the slave, if it wouldn't receive any packet within the period of first 6 connection interval, it will terminate the connection [4.5.2 Vol 6 Part B].
II. Connection parameters
Connection parameters are crucial for a connection to be established. They provide information
on how should the master and the slave communicate. The connection parameter is included in the Connect Request payload as follow [184.108.40.206 Vol6 PartB]:
Interval: defines the interval of the connection. How frequently the master will send a connection event packet to slave. Connection interval = interval * 1.25ms.
Latency: Slave latency. The slave can skip waking up and response to the connection event from master to slave. The latency is the number of connect event the slave can skip. This is to save power on the slave side. When it has no data it can skip some connection events. But the sleeping period should not be too long so that the connection will timeout.
Timeout: How long would the master keep sending connection event without response from slave before terminate the connection.
ChM: Channel map, which channels will be used and which will not be used. 37 LSB bits represent the 37 channels can be used for connection packets. See PART 1 for the list of 40 channels for both advertising and connection.
Hop: The hop increment in the data channel selection. How big should the channel be jumped in side the channel map list. The algorithm is at Section 220.127.116.11 Vol 6 Part B
SCA: The worst case of the Sleep clock accuracy on the master. The slave uses this value in combination with the tolerance of its own sleep clock to determine how big should its RX window be opened to cope with the inaccuracy of the clock on the master. The higher the SCA the more power consumption the slave uses.
AA: Access address of the connection, each connection need an unique access address that both peer devices will use instead of using BED6 address as in advertising.
CRC Init: initialization value for the CRC calculation for linklayer
WinSize: TransmitWindowSize = WinSize * 1.25 ms
WinOffset: TransmitWindowOffset = WinOffset * 1.25 ms
Following is a sniffer trace that shows the connect request packet. You can find information about the connection in the connect request packet, including connection interval, connection timeout, etc, as discussed above. This is very useful for debugging and analyzing a connection.
There are 2 different whitelists can get involved when initiating the connection:
IV. Connection Terminating
A connection can be terminated when:
One of the peers voluntary terminates by sending LL_TERMINATE_IND PDU
Connection timed out. This is when one of the peer device failed to ACK or send a data channel packet within the connection timeout period.
It's failed to established. This is when the connection request is not received by the advertiser or if the advertiser rejected it.
There are several error codes can be used for the LL_TERMINATE_IND, this will match with the value of the reason variable in ble_gap_evt_disconnected_t struct when you receive BLE_GAP_EVT_DISCONNECTED event. Following is the common reason you usually receive:
REMOTE USER TERMINATED CONNECTION (0x13): The remote device/user terminated the connection.
BLE_HCI_CONNECTION_TIMEOUT (0x08): Connection timeout
CONNECTION TERMINATED BY LOCAL HOST (0x16): Disconnected because the local device terminated connection.
CONNECTION FAILED TO BE ESTABLISHED (0x3E): This is when the slave didn't receive the connect request or if it reject that connect request.
UNACCEPTABLE CONNECTION PARAMETERS (0x3B): This is when the slave want to disconnect because it won't accept the connection parameters from master.
Note that there are only two reasons should be used when calling sd_ble_gap_disconnect() which are REMOTE USER TERMINATED CONNECTION and UNACCEPTABLE CONNECTION PARAMETERS.
I. Data channel packet format
[Section 2 Part B Vol 6]
On linklayer, there is only one packet format for both advertising data packet and data channel packet (connection packet) as follow:
The Access Address is the address provided in the CONNECT REQ packet.
The PDU (Protocol Data Unit) of a data channel is as follow:
The header of the PDU is composed of :
The LLID tells if it's an empty packet (just for acknowledgment) or data PDU or control PDU.
NESN and SN is the sequence number for ACKing and flow control, that will be explained below.
MD: More data bit. When receive this the receiver knows that peer device want to send more data in this connection event. Our softdevice support up to 6 packets per connection event. Note that with S13x you have to configure the connection with high bandwidth to support 6 packets.
Length: The length of the payload and MIC (for encrypted connection). Maximum payload MTU (at the moment) that our softdevice support on Link Layer is 27 bytes. There are 4 byte header inside the PDU's payload, so there are 23 bytes max payload for L2CAP layer and with 3 byte header for ATT layer, there are 20 bytes actual payload for application. We will support longer L2CAP MTU in the future version of the S13x softdevice.
II. Acknowledgement and Flow Control
Link layer uses 2 bits for acknowledgement: transmitSeqNum and nextExpectedSeqNum. We will call it sn and nesn to distinguish from SN and NESN bits from the packet.
Basically, for both master and slave, when receiving a packet, the packet's NESN will be compared with the device's sn. If they are the same then it's an NAK from the peer and the device will have to resend the previous TX data. If not then it's an ACK, and the device will increase its sn and send new data and sn.
Secondly, SN from the packet will also be compared to the device nesn, if it's the same then it's new RX data in the packet from the peer and the device will increase its nesn (means ACK) before sending next packet.
[4.5.9 Vol 6 Part B]
This 2 comparisons are independent, so a packet can be an NACK but still can have new data and vise versa.
The SN and NESN of a packet that a device sent are equal to the sn and nesn it has at that moment.
When a device can't receive further packet for example when there is no RX buffer left, it can NACK the packet by not increasing nesn. This will tell the peer device to retransmit the TX old data.
The following figure describe how it works:
The sniffer trace bellow shows an example of NACK packets. The master in this case only has 1 RX buffer, so it will NACK any further packet from the Slave in the same connection event.
As shown in the image, on channel 22 after the first notification from Slave (#1044), the master NACK the next notification (#1046) by not increasing nesn (NESN on #1045 = NESN on #1047). On the slave side, when receiving #1047, the NESN on that packet = sn on the slave, meaning the slave has to resend TX data. The data is resent on packet #1048.
How a connection is established and maintained is controlled by GAP layer. You will find most APIs and Event for connection state in ble_gap.h file.
I. APIs provided by the softdevice:
- Start scanning for advertising packet and report when receives
sd_ble_gap_scan_start(ble_gap_scan_params_t const *p_scan_params))
- Start scanning for advertising packet and send a connect request if address matches:
sd_ble_gap_connect( ble_gap_addr_t const *p_peer_addr, ble_gap_scan_params_t const *p_scan_params, ble_gap_conn_params_t const *p_conn_params))
- Teminate a connection :
sd_ble_gap_disconnect(uint16_t conn_handle, uint8_t hci_status_code))
- Stop scanning:
- Stop connecting:
For scanning, we need to provide scan parameters to the Softdevice. This scan parameters include the scan window, scan interval, whitelist, active or passive scan. For connecting, beside scan parameters, we also have to provide the connection parameters which are connection interval, connection timeout, slave latency.
Note that only max_conn_interval will be used as connection interval but you still need to set:
7.5ms ≤ min_conn_interval ≤ max_conn_interval
II. GAP events you may receive when initiate/terminate connection:
BLE_GAP_EVT_ADV_REPORT : Occurs when you are scanning and get an advertising packet or a scan response packet. In this event, you can read the advertising data or scan response data and the address of the advertiser. From here, you can start a scan and connect command (sd_ble_gap_connect) to the peer device (base on the address) either by directly to the peer address, or by adding the peer address to the whitelist. The connect request will be sent the next time your device receive the advertising packet from the peer.
Each event comes with the parameters with ble_evt_t struct. For connected event you can find the role of the connection (if the role of the device is central or peripheral), address of the peer, if it's in whitelist or not and if it is, which id in the white list it is (ble_gap_evt_connected_t) . For disconnected event, you can find the reason of the disconnection ( ble_gap_evt_disconnected_t). This is important for debugging. The address of the peer device is not included but you can use conn_handle inside ble_gap_evt_t to find which connection caused the event.
III. Example code
Although now we move to S140, this one is still very help! Many thanks Bui!
Please update these posts for newer SDKs, thanks!
@Andrzej: This is pretty old blog and the information here only applied for S132 v2.0 and older. If you use S132v4.0 please checkout the migration guide to find how to configure bandwidth. The MTU is also updated so that it can carry larger MTU. Please have a look at the release notes.
Very helpful, thanks. I would need a bit more accuracy on following:
"Note that with S13x you have to configure the connection with high bandwidth to support 6 packets" - What API function should I call to enable this?
"Maximum payload MTU (at the moment) that our softdevice support on Link Layer is 27 bytes" - Which excact version of your softdevie does it concern? I use S132 4.0.2, but I don't know if "at the moment" still applies.
Can you make up the text to contain these details? It will be far more usable to look at the article than going through all the comments that will appear here.
Thanks for this. It really brings more light into the BLE.