Implementing a Custom BLE GATT Service for Reliable Bulk Data Transfer with Flow Control and Error Recovery
Implementing a Custom BLE GATT Service for Reliable Bulk Data Transfer with Flow Control and Error Recovery
Bluetooth Low Energy (BLE) is widely used for low-power, short-range communication, but its standard Generic Attribute Profile (GATT) service model is optimized for small, periodic data exchanges. For applications requiring reliable bulk data transfer—such as firmware updates, sensor data logs, or file synchronization—the standard GATT procedures can be insufficient due to limited MTU sizes, lack of inherent flow control, and minimal error recovery. This article presents a custom GATT service design that addresses these limitations by incorporating flow control, error recovery, and efficient bulk data handling, drawing inspiration from the Object Transfer Service (OTS) specification and the Scan Parameters Service (ScPS) for structured service definitions.
Understanding the Limitations of Standard GATT for Bulk Data
BLE GATT is built around client-server interactions using characteristics and descriptors. The maximum transmission unit (MTU) in BLE 4.0/4.1 is typically 23 bytes, and even with extended MTU (up to 247 bytes in BLE 4.2+), the protocol remains request-response oriented. For bulk data, the client must issue multiple write requests (Write Request or Write Command) or read requests, each requiring acknowledgments or notifications. This sequential nature leads to low throughput (often below 10-20 KB/s) and no built-in mechanism for flow control or packet loss recovery beyond the link-layer retransmissions. Additionally, the GATT protocol does not provide a session-level acknowledgment for partial data transfers, making it difficult to resume interrupted transfers.
Designing a Custom Bulk Data Transfer Service
To overcome these limitations, we define a custom GATT service with the following characteristics:
- Service UUID: A 128-bit vendor-specific UUID (e.g.,
12345678-1234-5678-1234-56789abcdef0). - Characteristics:
- Data Transfer Characteristic: Used for sending bulk data chunks. Supports Write Without Response (for high throughput) and Notify (for server-to-client transfers).
- Flow Control Characteristic: A writeable characteristic where the receiver can set the maximum number of outstanding packets (credit-based flow control).
- Status Characteristic: Indicates transfer state (IDLE, IN_PROGRESS, COMPLETE, ERROR).
- Error Recovery Characteristic: Allows the client to request retransmission of specific packet sequence numbers.
This service is analogous to the Object Transfer Service (OTS) which defines an Object Transfer Channel (OTC) over L2CAP for bulk data, but we implement flow control directly at the GATT level to avoid the complexity of L2CAP CoC. The Scan Parameters Service (ScPS) demonstrates how a service can store client parameters for optimization—here, we store flow control credits and error recovery state.
Flow Control Implementation
Flow control is essential to prevent buffer overflow on the receiver side. We implement a credit-based system:
- The receiver initializes a credit counter (e.g., 10) and writes it to the Flow Control Characteristic.
- The sender transmits data chunks only when credits are available. Each chunk reduces the credit count by one.
- The receiver processes each chunk and, when ready, writes a new credit value (incrementing the available credits).
- If credits reach zero, the sender must stop until new credits are received.
Example credit update from the receiver side (embedded C with Zephyr RTOS):
// Receiver: after processing a data chunk, update credits
static void process_data_chunk(uint8_t *data, uint16_t len) {
// Process the chunk (e.g., write to flash)
// ...
// Increment available credits
current_credits++;
if (current_credits > MAX_CREDITS) {
current_credits = MAX_CREDITS;
}
// Write new credit value to Flow Control Characteristic
uint8_t credit_val = current_credits;
bt_gatt_notify(NULL, &flow_ctrl_chrc, &credit_val, sizeof(credit_val));
}
This approach ensures that the receiver can pace the data flow according to its processing capacity, preventing buffer overruns. The credit value can also be used to indicate the receiver’s available memory (e.g., in bytes).
Error Recovery Mechanism
Bulk data transfers over BLE are susceptible to packet loss due to interference or link instability. While the BLE link layer provides retransmission at the packet level, it may not recover from persistent errors or missed notifications. Our service implements a sequence number-based recovery:
- Each data chunk includes a 16-bit sequence number in the first two bytes.
- The receiver maintains a bitmap of received sequence numbers (up to 1024 chunks).
- If a gap is detected (e.g., after a timeout or explicit NACK), the receiver writes the missing sequence numbers to the Error Recovery Characteristic.
- The sender retransmits only those specific chunks.
Example sender-side retransmission logic:
// Sender: handle retransmission request
void on_error_recovery_write(struct bt_conn *conn, const uint8_t *data, uint16_t len) {
// data contains a list of sequence numbers to retransmit (2 bytes each)
uint16_t num_seq = len / 2;
for (uint16_t i = 0; i < num_seq; i++) {
uint16_t seq = (data[2*i] << 8) | data[2*i+1];
// Find the chunk buffer with this sequence number
uint8_t *chunk = find_chunk_by_seq(seq);
if (chunk) {
// Retransmit using Write Without Response
bt_gatt_write_without_response(conn, data_chrc_handle, chunk, chunk_len, false);
}
}
}
This selective retransmission is more efficient than resending the entire transfer and is inspired by the OTS checksum feature which allows verifying object integrity. In our service, the receiver can compute a CRC over received data and request retransmission of corrupted chunks.
Performance Considerations and Optimization
To achieve high throughput, the following parameters should be tuned:
- MTU Size: Use the maximum MTU supported by both devices (typically 247 bytes for BLE 4.2+). Each data chunk should be MTU – 3 bytes (for ATT header) – 2 bytes (sequence number) = 242 bytes.
- Connection Interval: Use a minimal connection interval (7.5 ms) to reduce latency between packets.
- Credits: A larger credit window (e.g., 20-50) allows the sender to pipeline multiple chunks before waiting for acknowledgments, improving throughput.
- Data Chunk Size: For Write Without Response, the effective throughput can reach 100-200 KB/s with optimal settings, depending on the BLE chip and stack.
Example throughput calculation: With MTU=247, data payload=242 bytes, connection interval=7.5 ms, and 30 credits, the sender can transmit 30 chunks in one connection event (if the controller supports multiple packets per event). This yields a theoretical throughput of (242 * 30) / 0.0075 ≈ 968 KB/s, but practical values are lower due to stack overhead and radio interference.
Comparison with Standard BLE Bulk Transfer Solutions
The standard approach for bulk data in BLE is to use L2CAP Connection-Oriented Channels (CoC), as defined in the Object Transfer Service (OTS). OTS provides a dedicated channel with its own flow control (credit-based) and optional checksum. However, L2CAP CoC requires support from the BLE controller and stack, which may not be available on all devices (especially older ones). Our custom GATT service works on any BLE 4.0+ device and can be implemented with minimal stack modifications. The trade-off is slightly lower efficiency due to GATT overhead (3 bytes per packet) and the need to manage flow control and sequence numbers at the application layer.
Another alternative is to use the GATT Long Write procedure, which allows writing up to 512 bytes (with MTU=247, it requires multiple packets). However, Long Write is a blocking operation and does not support flow control or selective retransmission. Our service provides finer-grained control and error recovery.
Integration with Existing BLE Profiles
The custom service can be combined with standard services like the Scan Parameters Service (ScPS) to optimize power consumption. For example, during a bulk transfer, the server can adjust its scan parameters (scan interval, window) to prioritize data reception, similar to how ScPS allows a client to store scan parameters on the server. The ScPS specification (v10) defines the "Scan Interval Window" characteristic for this purpose. In our implementation, the server could write its current scan parameters to the client to reduce latency during transfers.
Conclusion
Implementing a custom BLE GATT service for bulk data transfer with flow control and error recovery is a practical solution for applications that require high reliability and throughput without relying on L2CAP CoC. By incorporating credit-based flow control and sequence number-based retransmission, the service can achieve robust data transfer over lossy BLE links. The design is flexible enough to be adapted for various use cases, from IoT sensor data collection to over-the-air firmware updates. Developers should carefully tune MTU, connection parameters, and credit windows based on their hardware and application requirements. For further optimization, consider integrating with services like ScPS for power management and OTS for standardized object handling where supported.
常见问题解答
问: What are the main limitations of standard BLE GATT for bulk data transfer, and how does the custom service address them?
答: Standard BLE GATT is optimized for small, periodic data exchanges with limited MTU sizes (e.g., 23 bytes in BLE 4.0/4.1, up to 247 bytes in BLE 4.2+), a request-response sequential model, and no inherent flow control or session-level error recovery. This results in low throughput (often below 10-20 KB/s) and difficulty resuming interrupted transfers. The custom service overcomes these by implementing credit-based flow control via a Flow Control Characteristic, allowing the receiver to set the maximum number of outstanding packets; a Data Transfer Characteristic supporting Write Without Response for high throughput; and an Error Recovery Characteristic for requesting retransmission of specific packet sequence numbers.
问: How does credit-based flow control work in this custom GATT service, and why is it important?
答: Credit-based flow control is implemented via a writeable Flow Control Characteristic, where the receiver sets the maximum number of outstanding packets (credits) the sender can transmit without acknowledgment. The sender must wait for credits to be replenished before sending more data. This prevents buffer overflow on the receiver side and ensures stable throughput, as the receiver can throttle the sender based on its processing capacity. It is important because standard GATT lacks such a mechanism, leading to potential data loss or inefficiency during bulk transfers.
问: What is the role of the Error Recovery Characteristic, and how does it differ from standard BLE link-layer retransmissions?
答: The Error Recovery Characteristic allows the client to request retransmission of specific packet sequence numbers that were lost or corrupted during transfer. This is a session-level mechanism that operates above the BLE link layer, which only handles immediate retransmissions at the packet level. Unlike link-layer retransmissions, which are transparent to the application and may not recover from all errors (e.g., if a packet is dropped after acknowledgment), the Error Recovery Characteristic provides a way to resume transfers from a known point, reducing the need to restart the entire data transfer.
问: Why does the article choose to implement flow control at the GATT level rather than using L2CAP Connection-Oriented Channels (CoC)?
答: The article chooses GATT-level flow control to avoid the complexity of L2CAP CoC, which requires additional configuration and may not be supported on all BLE devices. By implementing flow control directly via a custom characteristic (e.g., Flow Control Characteristic), the solution remains compatible with standard GATT profiles and does not require changes to the underlying L2CAP layer. This simplifies development while still providing credit-based flow control for reliable bulk data transfer.
问: What are the key characteristics defined in this custom GATT service, and what is each used for?
答: The custom service defines four key characteristics: (1) Data Transfer Characteristic, used for sending bulk data chunks via Write Without Response (client-to-server) or Notify (server-to-client); (2) Flow Control Characteristic, a writeable characteristic where the receiver sets the maximum number of outstanding packets for credit-based flow control; (3) Status Characteristic, which indicates the transfer state (IDLE, IN_PROGRESS, COMPLETE, ERROR); and (4) Error Recovery Characteristic, allowing the client to request retransmission of specific packet sequence numbers for error recovery.
💬 欢迎到论坛参与讨论: 点击这里分享您的见解或提问
