Using nrf connect SDK 2.5.0
The nrf device is an L2CAP CoC server. I am using an RPi 4 to test with. The application is for transferring data through UART to another chip on the board to perform OTA updates. The connection sets up and I can transfer data successfully from the RPi to the nrf, but I only get 1 credit per connection interval, so throughput is limited. I have a connection interval of 7.5ms, an MTU of 245, so 245/7.5e-3 = 32KBps, which is roughly what my setup achieves, however I should be able to get 3 credits per interval (PHY 1M), so 98KBps. I want to fix this as some clients may have a larger min connection interval, so this issue would be exacerbated in that case.
I have tried increasing CONFIG_BT_BUF_ACL_RX_COUNT
a snippet of the prj:
int configure_softdevice_buffers(void)
{
sdc_cfg_t cfg;
cfg.buffer_cfg.rx_packet_count = CONFIG_BT_BUF_ACL_RX_COUNT;
cfg.buffer_cfg.tx_packet_count = CONFIG_BT_BUF_ACL_TX_COUNT;
cfg.buffer_cfg.rx_packet_size = CONFIG_BT_CTLR_DATA_LENGTH_MAX;
cfg.buffer_cfg.tx_packet_size = CONFIG_BT_CTLR_DATA_LENGTH_MAX;
return sdc_cfg_set(SDC_DEFAULT_RESOURCE_CFG_TAG, SDC_CFG_TYPE_BUFFER_CFG, &cfg);
}
static int my_bt_low_level_init(void)
{
int ret = configure_softdevice_buffers();
if (ret) {
printk("SDC Config failed: %d\n", ret);
} else {
printk("SDC Config success\n");
}
return 0;
}
// Use PRE_KERNEL_1 to ensure this runs before the BT stack starts
SYS_INIT(my_bt_low_level_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);My server code is as basic as possible, except I have tried manually allocating a large enough net buf pool (size 20) using the alloc_buff callback. I tried without doing this initially with the same result. My recv callback does not do anything with the data currently, I just want to test the L2CAP connection speed first before adding UART.
#include <zephyr/kernel.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/l2cap.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(l2cap_channel);
#include "l2cap_channel.h"
/* Must match client */
#define L2CAP_PSM 0x0081
#define L2CAP_MTU 245
#define RX_BUFF_NUM 20
#define RX_BUFF_LENGTH 251
#define RX_BUFF_USER_DATA_SIZE 8
static struct bt_l2cap_le_chan l2cap_chan;
NET_BUF_POOL_FIXED_DEFINE(net_buff_pool_rx, RX_BUFF_NUM, RX_BUFF_LENGTH, RX_BUFF_USER_DATA_SIZE, NULL);
static uint32_t bytes_received = 0;
// L2CAP CALLBACKS
// --------------------------------------------------------
static void l2cap_connected(struct bt_l2cap_chan *chan)
{
LOG_INF("L2CAP CoC connected");
}
static void l2cap_disconnected(struct bt_l2cap_chan *chan)
{
LOG_INF("L2CAP CoC disconnected");
}
static int l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
{
bytes_received += buf->len;
return 0;
}
static struct net_buf *l2cap_chan_alloc_buf(struct bt_l2cap_chan *chan)
{
struct net_buf *buf = net_buf_alloc(&net_buff_pool_rx, K_NO_WAIT);
if (buf) {
LOG_INF("Allocated buf for credit");
} else {
LOG_ERR("Failed to allocate buf for credit");
}
return buf;
}
// CHANNEL OPS
// --------------------------------------------------------
static struct bt_l2cap_chan_ops l2cap_ops = {
.connected = l2cap_connected,
.disconnected = l2cap_disconnected,
.recv = l2cap_recv,
.alloc_buf = l2cap_chan_alloc_buf,
};
// ACCEPT CALLBACK
// --------------------------------------------------------
static int l2cap_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan)
{
LOG_INF("L2CAP CoC accept");
struct bt_l2cap_le_chan *le_chan = &l2cap_chan; // Ensure this is the LE struct
// Force reset the RX state before assigning
memset(&le_chan->rx, 0, sizeof(le_chan->rx));
le_chan->chan.ops = &l2cap_ops;
le_chan->rx.mtu = L2CAP_MTU;
le_chan->rx.mps = L2CAP_MTU;
le_chan->rx.init_credits = RX_BUFF_NUM / 2;
*chan = &le_chan->chan;
return 0;
}
// L2CAP SERVER
// --------------------------------------------------------
static struct bt_l2cap_server l2cap_server = {
.psm = L2CAP_PSM,
.sec_level = BT_SECURITY_L1, // no auth no encryption
.accept = l2cap_accept,
};
// PUBLIC METHODS
// --------------------------------------------------------
int l2cap_channel_init()
{
return bt_l2cap_server_register(&l2cap_server);
}
Here is my btmon output from the RPi. it shows that I am only receiving 1 credit per connection interval even though the packet size that I am sending (30) is way less than the MTU. Note that this is not the same log as for the 32KBps connection, this is me testing with a lower MTU to prove out that there should be enough buffer on the controller to handle multiple credits.
< HCI Command: LE Set Scan Parameters (0x08|0x000b) plen 7 #1 4.846002
Type: Passive (0x00)
Interval: 60.000 msec (0x0060)
Window: 60.000 msec (0x0060)
Own address type: Public (0x00)
Filter policy: Ignore not in white list (0x01)
> HCI Event: Command Complete (0x0e) plen 4 #2 4.846421
LE Set Scan Parameters (0x08|0x000b) ncmd 1
Status: Success (0x00)
< HCI Command: LE Set Scan Enable (0x08|0x000c) plen 2 #3 4.846526
Scanning: Enabled (0x01)
Filter duplicates: Enabled (0x01)
> HCI Event: Command Complete (0x0e) plen 4 #4 4.846851
LE Set Scan Enable (0x08|0x000c) ncmd 1
Status: Success (0x00)
> HCI Event: LE Meta Event (0x3e) plen 35 #5 5.142090
LE Advertising Report (0x02)
Num reports: 1
Event type: Connectable undirected - ADV_IND (0x00)
Address type: Random (0x01)
Address: D7:85:74:5F:87:45 (Static)
Data length: 23
Flags: 0x06
LE General Discoverable Mode
BR/EDR Not Supported
Name (complete): SX00000
Company: Ericsson Technology Licensing (0)
Data: 000000000000
RSSI: -35 dBm (0xdd)
< HCI Command: LE Set Scan Enable (0x08|0x000c) plen 2 #6 5.142149
Scanning: Disabled (0x00)
Filter duplicates: Disabled (0x00)
> HCI Event: Command Complete (0x0e) plen 4 #7 5.144100
LE Set Scan Enable (0x08|0x000c) ncmd 1
Status: Success (0x00)
< HCI Command: LE Create Connection (0x08|0x000d) plen 25 #8 5.144154
Scan interval: 60.000 msec (0x0060)
Scan window: 60.000 msec (0x0060)
Filter policy: White list is not used (0x00)
Peer address type: Random (0x01)
Peer address: D7:85:74:5F:87:45 (Static)
Own address type: Public (0x00)
Min connection interval: 7.50 msec (0x0006)
Max connection interval: 7.50 msec (0x0006)
Connection latency: 0 (0x0000)
Supervision timeout: 4000 msec (0x0190)
Min connection length: 0.000 msec (0x0000)
Max connection length: 0.000 msec (0x0000)
> HCI Event: Command Status (0x0f) plen 4 #9 5.144672
LE Create Connection (0x08|0x000d) ncmd 1
Status: Success (0x00)
> HCI Event: LE Meta Event (0x3e) plen 19 #10 5.349786
LE Connection Complete (0x01)
Status: Success (0x00)
Handle: 64
Role: Master (0x00)
Peer address type: Random (0x01)
Peer address: D7:85:74:5F:87:45 (Static)
Connection interval: 7.50 msec (0x0006)
Connection latency: 0 (0x0000)
Supervision timeout: 4000 msec (0x0190)
Master clock accuracy: 0x00
@ MGMT Event: Device Connected (0x000b) plen 36 {0x0001} 5.349817
LE Address: D7:85:74:5F:87:45 (Static)
Flags: 0x00000008
Unknown device flag (0x00000008)
Data length: 23
Flags: 0x06
LE General Discoverable Mode
BR/EDR Not Supported
Name (complete): SX00000
Company: Ericsson Technology Licensing (0)
Data: 000000000000
< HCI Command: LE Read Remote Used Features (0x08|0x0016) plen 2 #11 5.349912
Handle: 64
> HCI Event: Command Status (0x0f) plen 4 #12 5.350757
LE Read Remote Used Features (0x08|0x0016) ncmd 1
Status: Success (0x00)
> ACL Data RX: Handle 64 flags 0x02 dlen 7 #13 5.366017
ATT: Exchange MTU Request (0x02) len 2
Client RX MTU: 247
> HCI Event: LE Meta Event (0x3e) plen 12 #14 5.366685
LE Read Remote Used Features (0x04)
Status: Success (0x00)
Handle: 64
Features: 0x2d 0x00 0x00 0x00 0x00 0x00 0x00 0x00
LE Encryption
Extended Reject Indication
Slave-initiated Features Exchange
LE Data Packet Length Extension
< ACL Data TX: Handle 64 flags 0x00 dlen 18 #15 5.366734
LE L2CAP: LE Connection Request (0x14) ident 1 len 10
PSM: 129 (0x0081)
Source CID: 64
MTU: 672
MPS: 247
Credits: 3
< ACL Data TX: Handle 64 flags 0x00 dlen 7 #16 5.367263
ATT: Exchange MTU Response (0x03) len 2
Server RX MTU: 517
< ACL Data TX: Handle 64 flags 0x00 dlen 7 #17 5.367276
ATT: Exchange MTU Request (0x02) len 2
Client RX MTU: 517
> HCI Event: LE Meta Event (0x3e) plen 11 #18 5.388874
LE Data Length Change (0x07)
Handle: 64
Max TX octets: 251
Max TX time: 2120
Max RX octets: 251
Max RX time: 2120
> ACL Data RX: Handle 64 flags 0x02 dlen 18 #19 5.396227
LE L2CAP: LE Connection Response (0x15) ident 1 len 10
Destination CID: 64
MTU: 30
MPS: 32
Credits: 1
Result: Connection successful (0x0000)
> HCI Event: Number of Completed Packets (0x13) plen 5 #20 5.396619
Num handles: 1
Handle: 64
Count: 2
> ACL Data RX: Handle 64 flags 0x02 dlen 7 #21 5.411145
ATT: Exchange MTU Response (0x03) len 2
Server RX MTU: 247
< ACL Data TX: Handle 64 flags 0x00 dlen 7 #22 5.411479
ATT: Read Request (0x0a) len 2
Handle: 0x0004
> HCI Event: Number of Completed Packets (0x13) plen 5 #23 5.418762
Num handles: 1
Handle: 64
Count: 2
> ACL Data RX: Handle 64 flags 0x02 dlen 12 #24 5.426104
ATT: Read Response (0x0b) len 7
Value: 53583030303030
< ACL Data TX: Handle 64 flags 0x00 dlen 7 #25 5.426409
ATT: Read Request (0x0a) len 2
Handle: 0x0006
> ACL Data RX: Handle 64 flags 0x02 dlen 7 #26 5.441071
ATT: Read Response (0x0b) len 2
Value: 0000
< ACL Data TX: Handle 64 flags 0x00 dlen 11 #27 5.441421
ATT: Read By Type Request (0x08) len 6
Handle range: 0x0001-0xffff
Attribute type: Unknown (0x2b3a)
> HCI Event: Number of Completed Packets (0x13) plen 5 #28 5.448773
Num handles: 1
Handle: 64
Count: 2
> ACL Data RX: Handle 64 flags 0x02 dlen 9 #29 5.456084
ATT: Error Response (0x01) len 4
Read By Type Request (0x08)
Handle: 0x0001
Error: Attribute Not Found (0x0a)
< ACL Data TX: Handle 64 flags 0x00 dlen 11 #30 5.456288
ATT: Read By Group Type Request (0x10) len 6
Handle range: 0x0001-0xffff
Attribute group type: Primary Service (0x2800)
> ACL Data RX: Handle 64 flags 0x02 dlen 18 #31 5.471163
ATT: Read By Group Type Response (0x11) len 13
Attribute data length: 6
Attribute group list: 2 entries
Handle range: 0x0001-0x0001
UUID: Generic Attribute Profile (0x1801)
Handle range: 0x0002-0x0006
UUID: Generic Access Profile (0x1800)
< ACL Data TX: Handle 64 flags 0x00 dlen 11 #32 5.471362
ATT: Read By Group Type Request (0x10) len 6
Handle range: 0x0007-0xffff
Attribute group type: Primary Service (0x2800)
> HCI Event: Number of Completed Packets (0x13) plen 5 #33 5.478772
Num handles: 1
Handle: 64
Count: 2
> ACL Data RX: Handle 64 flags 0x02 dlen 26 #34 5.486695
ATT: Read By Group Type Response (0x11) len 21
Attribute data length: 20
Attribute group list: 1 entry
Handle range: 0x0007-0x000c
UUID: Nordic UART Service (6e400001-b5a3-f393-e0a9-e50e24dcca9e)
< ACL Data TX: Handle 64 flags 0x00 dlen 11 #35 5.486873
ATT: Read By Group Type Request (0x10) len 6
Handle range: 0x000d-0xffff
Attribute group type: Primary Service (0x2800)
> ACL Data RX: Handle 64 flags 0x02 dlen 9 #36 5.501100
ATT: Error Response (0x01) len 4
Read By Group Type Request (0x10)
Handle: 0x000d
Error: Attribute Not Found (0x0a)
> HCI Event: Number of Completed Packets (0x13) plen 5 #37 5.639217
Num handles: 1
Handle: 64
Count: 1
< ACL Data TX: Handle 64 flags 0x00 dlen 31 #38 15.397047
Channel: 64 len 27 sdu 25 [PSM 129 mode LE Flow Control (0x80)] {chan 0}
19 00 00 00 02 20 2d 37 01 24 41 35 01 24 43 35 ..... -7.$A5.$C5
01 24 45 35 01 24 47 35 01 24 49 .$E5.$G5.$I
< ACL Data TX: Handle 64 flags 0x00 dlen 31 #39 15.397074
Channel: 64 len 27 sdu 25 [PSM 129 mode LE Flow Control (0x80)] {chan 0}
19 00 35 01 24 00 00 00 00 00 00 00 00 00 00 00 ..5.$...........
00 00 00 00 00 01 f3 01 24 4b 35 ........$K5
< ACL Data TX: Handle 64 flags 0x00 dlen 31 #40 15.397077
Channel: 64 len 27 sdu 25 [PSM 129 mode LE Flow Control (0x80)] {chan 0}
19 00 01 24 00 00 00 00 a1 f3 01 24 5f d0 01 24 ...$.......$_..$
7d 37 01 24 7d 37 01 24 7d 37 01 }7.$}7.$}7.
< ACL Data TX: Handle 64 flags 0x00 dlen 31 #41 15.397090
Channel: 64 len 27 sdu 25 [PSM 129 mode LE Flow Control (0x80)] {chan 0}
19 00 24 7d 37 01 24 7d 37 01 24 7d 37 01 24 7d ..$}7.$}7.$}7.$}
37 01 24 7d 37 01 24 7d 37 01 24 7.$}7.$}7.$
< ACL Data TX: Handle 64 flags 0x00 dlen 31 #42 15.397099
Channel: 64 len 27 sdu 25 [PSM 129 mode LE Flow Control (0x80)] {chan 0}
19 00 7d 37 01 24 7d 37 01 24 4d 35 01 24 5d 35 ..}7.$}7.$M5.$]5
01 24 7d 37 01 24 7d 37 01 24 7d .$}7.$}7.$}
< ACL Data TX: Handle 64 flags 0x00 dlen 31 #43 15.397107
Channel: 64 len 27 sdu 25 [PSM 129 mode LE Flow Control (0x80)] {chan 0}
19 00 37 01 24 7d 37 01 24 7d 37 01 24 7d 37 01 ..7.$}7.$}7.$}7.
24 7d 37 01 24 7d 37 01 24 7d 37 $}7.$}7.$}7
< ACL Data TX: Handle 64 flags 0x00 dlen 31 #44 15.397116
Channel: 64 len 27 sdu 25 [PSM 129 mode LE Flow Control (0x80)] {chan 0}
19 00 01 24 7d 37 01 24 7d 37 01 24 7d 37 01 24 ...$}7.$}7.$}7.$
6d 35 01 24 7d 37 01 24 7d 37 01 m5.$}7.$}7.
> HCI Event: Number of Completed Packets (0x13) plen 5 #45 15.402052
Num handles: 1
Handle: 64
Count: 2
< ACL Data TX: Handle 64 flags 0x00 dlen 31 #46 15.402094
Channel: 64 len 27 sdu 25 [PSM 129 mode LE Flow Control (0x80)] {chan 0}
19 00 24 7d 37 01 24 7d 37 01 24 7d 37 01 24 7d ..$}7.$}7.$}7.$}
37 01 24 7d 37 01 24 7d 37 01 24 7.$}7.$}7.$
< ACL Data TX: Handle 64 flags 0x00 dlen 31 #47 15.402102
Channel: 64 len 27 sdu 25 [PSM 129 mode LE Flow Control (0x80)] {chan 0}
19 00 7d 37 01 24 7d 37 01 24 7d 37 01 24 7d 37 ..}7.$}7.$}7.$}7
01 24 7d 37 01 24 7d 37 01 24 7d .$}7.$}7.$}
> ACL Data RX: Handle 64 flags 0x02 dlen 12 #48 15.402763
LE L2CAP: LE Flow Control Credit (0x16) ident 1 len 4
Source CID: 64
Credits: 1
> ACL Data RX: Handle 64 flags 0x02 dlen 12 #49 15.403728
LE L2CAP: LE Flow Control Credit (0x16) ident 2 len 4
Source CID: 64
Credits: 1
> HCI Event: Number of Completed Packets (0x13) plen 5 #50 15.403878
Num handles: 1
Handle: 64
Count: 2
< ACL Data TX: Handle 64 flags 0x00 dlen 31 #51 15.403898
Channel: 64 len 27 sdu 25 [PSM 129 mode LE Flow Control (0x80)] {chan 0}
19 00 37 01 24 7d 37 01 24 00 00 00 00 7d 37 01 ..7.$}7.$....}7.
24 7d 37 01 24 7d 37 01 24 7d 37 $}7.$}7.$}7
< ACL Data TX: Handle 64 flags 0x00 dlen 12 #52 15.403905
LE L2CAP: Disconnection Request (0x06) ident 2 len 4
Destination CID: 64
Source CID: 64
> ACL Data RX: Handle 64 flags 0x02 dlen 12 #53 15.408912
LE L2CAP: LE Flow Control Credit (0x16) ident 3 len 4
Source CID: 64
Credits: 1
> ACL Data RX: Handle 64 flags 0x02 dlen 12 #54 15.409706
LE L2CAP: LE Flow Control Credit (0x16) ident 4 len 4
Source CID: 64
Credits: 1
> HCI Event: Number of Completed Packets (0x13) plen 5 #55 15.410967
Num handles: 1
Handle: 64
Count: 2
> ACL Data RX: Handle 64 flags 0x02 dlen 12 #56 15.410981
LE L2CAP: LE Flow Control Credit (0x16) ident 5 len 4
Source CID: 64
Credits: 1
> ACL Data RX: Handle 64 flags 0x02 dlen 12 #57 15.411851
LE L2CAP: LE Flow Control Credit (0x16) ident 6 len 4
Source CID: 64
Credits: 1
> HCI Event: Number of Completed Packets (0x13) plen 5 #58 15.411988
Num handles: 1
Handle: 64
Count: 2
> ACL Data RX: Handle 64 flags 0x02 dlen 12 #59 15.416413
LE L2CAP: LE Flow Control Credit (0x16) ident 7 len 4
Source CID: 64
Credits: 1
> ACL Data RX: Handle 64 flags 0x02 dlen 12 #60 15.417195
LE L2CAP: LE Flow Control Credit (0x16) ident 8 len 4
Source CID: 64
Credits: 1
> HCI Event: Number of Completed Packets (0x13) plen 5 #61 15.417416
Num handles: 1
Handle: 64
Count: 2
> ACL Data RX: Handle 64 flags 0x02 dlen 12 #62 15.418040
LE L2CAP: LE Flow Control Credit (0x16) ident 9 len 4
Source CID: 64
Credits: 1
> ACL Data RX: Handle 64 flags 0x02 dlen 12 #63 15.423739
LE L2CAP: Disconnection Response (0x07) ident 2 len 4
Destination CID: 64
Source CID: 64
> HCI Event: Number of Completed Packets (0x13) plen 5 #64 15.639354
Num handles: 1
Handle: 64
Count: 1