How to change MTU size of BLE?

Hello.

We are looking for a way to increase MTU size from 20 to more in BLE. Currently we get 20 byte packets or send whole strings chopped in 20 bytes which gives overhead on the application side to glue packets together and interpret.

Try calling:

int hal_ble_gatt_set_att_mtu(size_t att_mtu, void* reserved)

Pass nullptr for reserved. You shouldn’t need to add any include files.

The minimum MTU is 23 and the maximum appears to be 247.

I haven’t tested it, but that looks like how you do it from looking at the source.

I’d guess you need to set it before opening a connection.

Well it returns zero (success). However any kind of calling, before, after, or during setup renders no results, the packets are as were - 20 bytes max. More than that, the Particle Tracker stalls the reception without any reason at some point, until the peripheral disconnects after timeout.

The only other suggestion I have is maybe if you turn debugging at trace level there will be a useful log message shown. There are a number of them in the BLE code, and maybe that will provide a clue of why it’s not working.

SerialLogHandler logHandler(LOG_LEVEL_TRACE);

Also, it’s a negotiation between both sides, so both sides need to allow a larger size.

Relevant log gives only something like this:

0001986159 [wiring.ble] TRACE: New peripheral is connected.
0001986159 [wiring.ble] TRACE: Start discovering services.
0001986431 [wiring.ble] TRACE: Start discovering characteristics of service: 1800.
0001986791 [wiring.ble] TRACE: Characteristic discovered.
0001986792 [wiring.ble] TRACE: Start discovering characteristics of service: 1801.
0001987061 [wiring.ble] TRACE: Characteristic discovered.
0001987062 [wiring.ble] TRACE: Start discovering characteristics of service: FE59.
0001987601 [wiring.ble] TRACE: Characteristic discovered.
0001987601 [wiring.ble] TRACE: Start discovering characteristics of service: 6E400001-B5A3-F393-E0A9-E50E24DCCA9E.
0001988590 [wiring.ble] TRACE: Characteristic discovered.
0001988770 [hal.ble] ERROR: BLE read characteristic failed: 258, handle: 25.
0002009631 [wiring.ble] TRACE: New peripheral is connected.
0002009631 [wiring.ble] TRACE: Start discovering services.
0002009948 [wiring.ble] TRACE: Start discovering characteristics of service: 1800.
0002010308 [wiring.ble] TRACE: Characteristic discovered.
0002010308 [wiring.ble] TRACE: Start discovering characteristics of service: 1801.
0002010578 [wiring.ble] TRACE: Characteristic discovered.
0002010578 [wiring.ble] TRACE: Start discovering characteristics of service: FE59.
0002011117 [wiring.ble] TRACE: Characteristic discovered.
0002011118 [wiring.ble] TRACE: Start discovering characteristics of service: 6E400001-B5A3-F393-E0A9-E50E24DCCA9E.
0002012197 [wiring.ble] TRACE: Characteristic discovered.
0002053413 [wiring.ble] TRACE: Disconnected by remote device.
0002554241 [wiring.ble] TRACE: New peripheral is connected.
0002554242 [wiring.ble] TRACE: Start discovering services.
0002554468 [wiring.ble] TRACE: Start discovering characteristics of service: 1800.
0002554828 [wiring.ble] TRACE: Characteristic discovered.
0002554829 [wiring.ble] TRACE: Start discovering characteristics of service: 1801.
0002555098 [wiring.ble] TRACE: Characteristic discovered.
0002555098 [wiring.ble] TRACE: Start discovering characteristics of service: FE59.
0002555638 [wiring.ble] TRACE: Characteristic discovered.
0002555639 [wiring.ble] TRACE: Start discovering characteristics of service: 6E400001-B5A3-F393-E0A9-E50E24DCCA9E.
0002556628 [wiring.ble] TRACE: Characteristic discovered.

Bottomline. This technique did not work. Please confirm: changing MTU beyond 20 bytes is impossible on the Device OS.

It does appear to be impossible to change the BLE MTU in current versions of Device OS.

New information: MTU negotiation should work.

The Particle device should be requesting a MTU of 247. The other side may be negotiating it down to 23.

If you are able to build a debug build in Workbench and edit the ble_hal.cpp file to insert these lines at the top, you can get even more detailed debugging info.

#define DEBUG_BUILD
#undef LOG_COMPILE_TIME_LEVEL

You should be able to get a log like this, which will include more useful information:

0000020625 [hal.ble] TRACE: BLE role: 1, connection handle: 3
0000020625 [hal.ble] TRACE: | interval(ms)  latency  timeout(ms) |
0000020625 [hal.ble] TRACE:   36*1.25          0       500*10
0000020626 [hal.ble] TRACE: Attempts to exchange ATT_MTU if needed.
0000020627 [system.ctrl.ble] TRACE: Connected
0000021193 [hal.ble] TRACE: | interval(ms)  latency  timeout(ms) |
0000021194 [hal.ble] TRACE:   6*1.25          0       500*10
0000021425 [hal.ble] TRACE: Request to change ATT_MTU from 23 to 247
0000021448 [hal.ble] TRACE: Effective ATT MTU: 247.
0000021531 [hal.ble] TRACE: | interval(ms)  latency  timeout(ms) |
0000021531 [hal.ble] TRACE:   36*1.25          0       500*10
0000022091 [hal.ble] TRACE: hal_ble_gatt_server_notify_characteristic_value().
0000022235 [hal.ble] TRACE: hal_ble_gatt_server_notify_characteristic_value().
0000022318 [hal.ble] TRACE: hal_ble_gatt_server_notify_characteristic_value().
0000022875 [system.ctrl.ble] TRACE: Handshake done
2 Likes

Looks like it does fail at setting the MTU.

	Line 34: 0000487877 [hal.ble] TRACE: hal_ble_gap_start_scan().
	Line 35: 0000487878 [hal.ble] TRACE: | interval(ms)   window(ms)   timeout(ms) |
	Line 36: 0000487879 [hal.ble] TRACE:   160*0.625        80*0.625      5000
	Line 39: 0000492838 [hal.ble] TRACE: hal_ble_gap_start_scan().
	Line 40: 0000492840 [hal.ble] TRACE: | interval(ms)   window(ms)   timeout(ms) |
	Line 41: 0000492840 [hal.ble] TRACE:   160*0.625        80*0.625      5000
	Line 47: 0000497795 [hal.ble] TRACE: hal_ble_gap_start_scan().
	Line 48: 0000497796 [hal.ble] TRACE: | interval(ms)   window(ms)   timeout(ms) |
	Line 49: 0000497797 [hal.ble] TRACE:   160*0.625        80*0.625      5000
	Line 52: 0000502754 [hal.ble] TRACE: hal_ble_gap_start_scan().
	Line 53: 0000502754 [hal.ble] TRACE: | interval(ms)   window(ms)   timeout(ms) |
	Line 54: 0000502755 [hal.ble] TRACE:   160*0.625        80*0.625      5000
	Line 60: 0000507710 [hal.ble] TRACE: hal_ble_gap_start_scan().
	Line 61: 0000507711 [hal.ble] TRACE: | interval(ms)   window(ms)   timeout(ms) |
	Line 62: 0000507711 [hal.ble] TRACE:   160*0.625        80*0.625      5000
	Line 65: 0000512668 [hal.ble] TRACE: hal_ble_gap_start_scan().
	Line 66: 0000512668 [hal.ble] TRACE: | interval(ms)   window(ms)   timeout(ms) |
	Line 67: 0000512669 [hal.ble] TRACE:   160*0.625        80*0.625      5000
	Line 73: 0000517625 [hal.ble] TRACE: hal_ble_gap_start_scan().
	Line 74: 0000517625 [hal.ble] TRACE: | interval(ms)   window(ms)   timeout(ms) |
	Line 75: 0000517626 [hal.ble] TRACE:   160*0.625        80*0.625      5000
	Line 78: 0000522582 [hal.ble] TRACE: hal_ble_gap_start_scan().
	Line 79: 0000522584 [hal.ble] TRACE: | interval(ms)   window(ms)   timeout(ms) |
	Line 80: 0000522584 [hal.ble] TRACE:   160*0.625        80*0.625      5000
	Line 86: 0000527541 [hal.ble] TRACE: hal_ble_gap_start_scan().
	Line 87: 0000527541 [hal.ble] TRACE: | interval(ms)   window(ms)   timeout(ms) |
	Line 88: 0000527541 [hal.ble] TRACE:   160*0.625        80*0.625      5000
	Line 89: 0000532495 [hal.ble] TRACE: ble_gatt_client_set_att_mtu().
	Line 91: 0000532496 [hal.ble] TRACE: hal_ble_gap_connect().
	Line 92: 0000532515 [hal.ble] TRACE: BLE role: 2, connection handle: 0
	Line 93: 0000532516 [hal.ble] TRACE: | interval(ms)  latency  timeout(ms) |
	Line 94: 0000532516 [hal.ble] TRACE:   36*1.25          0       500*10
	Line 95: 0000532517 [hal.ble] TRACE: Attempts to exchange ATT_MTU if needed.
	Line 98: 0000532518 [hal.ble] TRACE: hal_ble_gatt_client_discover_all_services().
	Line 100: 0000532788 [hal.ble] TRACE: hal_ble_gatt_client_discover_characteristics().
	Line 103: 0000533148 [hal.ble] TRACE: hal_ble_gatt_client_discover_characteristics().
	Line 104: 0000533316 [hal.ble] TRACE: Request to change ATT_MTU from 23 to 247
	Line 105: 0000533316 [hal.ble] TRACE: sd_ble_gattc_exchange_mtu_request() failed: 17
	Line 108: 0000533418 [hal.ble] TRACE: hal_ble_gatt_client_discover_characteristics().
	Line 111: 0000533958 [hal.ble] TRACE: hal_ble_gatt_client_discover_characteristics().
	Line 113: 0000534947 [hal.ble] TRACE: hal_ble_gatt_client_read().
	Line 114: 0000535037 [hal.ble] TRACE: hal_ble_gatt_client_read().
	Line 115: 0000535127 [hal.ble] ERROR: BLE read characteristic failed: 258, handle: 25.
	Line 116: 0000535127 [hal.ble] TRACE: hal_ble_gatt_client_configure_cccd().
	Line 117: 0000535217 [hal.ble] TRACE: hal_ble_gatt_client_configure_cccd().
	Line 118: 0000535307 [hal.ble] TRACE: hal_ble_gatt_client_configure_cccd().
	Line 119: 0000535397 [hal.ble] TRACE: ble_gatt_client_set_att_mtu().
	Line 123: 0000535399 [hal.ble] TRACE: hal_ble_gatt_client_write_without_response().
	Line 126: 0000535442 [hal.ble] TRACE: hal_ble_gatt_client_write_without_response().
	Line 127: 0000535487 [hal.ble] TRACE: hal_ble_gatt_client_write_without_response().
	Line 128: 0000535532 [hal.ble] TRACE: hal_ble_gatt_client_write_without_response().
	Line 129: 0000535577 [hal.ble] TRACE: hal_ble_gatt_client_write_without_response().
	Line 133: 0000537122 [hal.ble] TRACE: hal_ble_gatt_client_write_without_response().
	Line 134: 0000537152 [hal.ble] TRACE: hal_ble_gatt_client_write_without_response().
	Line 155: 0000547975 [hal.ble] TRACE: hal_ble_gap_start_scan().
	Line 156: 0000547976 [hal.ble] TRACE: | interval(ms)   window(ms)   timeout(ms) |
	Line 157: 0000547978 [hal.ble] TRACE:   160*0.625        80*0.625      5000
	Line 160: 0000552935 [hal.ble] TRACE: hal_ble_gap_start_scan().
	Line 161: 0000552935 [hal.ble] TRACE: | interval(ms)   window(ms)   timeout(ms) |
	Line 162: 0000552935 [hal.ble] TRACE:   160*0.625        80*0.625      5000

@Nexusmaster Key things are

0000535127 [hal.ble] ERROR: BLE read characteristic failed: 258, handle: 25.
0000533316 [hal.ble] TRACE: sd_ble_gattc_exchange_mtu_request() failed: 17

258 is BLE_GATT_STATUS_ATTERR_READ_NOT_PERMITTED.

17 is NRF_ERROR_BUSY. This looks like an internal error in BLE stack, potentially problem with MTU exchange with the peer or some issue with our usage of nRF52840 BLE stack. Taking BLE_GATT_STATUS_ATTERR_READ_NOT_PERMITTED into account, looks more like an issue with the peer.

Can you provide some info on what’s on the other side of the connection?

[Prph] Disconnected
[BLE   ] BLE_GAP_EVT_CONNECTED : Conn Handle = 0
[GAP   ] MAC = C2:EB:D2:D7:AF:14, Type = 1, Resolved = 0
[GAP   ] Conn Interval = 45.00 ms, Latency = 0, Supervisor Timeout = 5000 ms
[BLE   ] BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST : Conn Handle = 0
[GAP   ] ATT MTU is changed to 247
[BLE   ] BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP : Conn Handle = 0
[Prph] Connected to Boron-FC6K9Y, MAC: c2ebd2d7af14
[BLE   ] BLE_GAP_EVT_DISCONNECTED : Conn Handle = 0
[GAP   ] Disconnect Reason: REMOTE_USER_TERMINATED_CONNECTION

Where [GAP ] ATT MTU is changed to 247 switches, but peer.getCharacteristicByUUID(peerTxCharacteristic, txUuid) does not work anymore.
REMOTE_USER_TERMINATED_CONNECTION mean after some time the peripheral disconnects gracefully (this is normal, it is supposed to do according to our needs).