PAN network speed issues: PAN download speed around 30 KB/s, much lower than expected

- **Chip Model**: SF32LB58

- **SDK Version**: SiFli SDK 2.4.4

- **Reference Example**: SiFli-SDK/example/bt/pan

Causes Already Ruled Out

  • :white_check_mark: TCP window too small (increased to 8KB)

  • :white_check_mark: Sniff mode impact (tested with disabled sniff)

  • :white_check_mark: Application layer buffer too small (increased to 8KB)

  • :white_check_mark: Excessive CPU yielding (tested without yielding)

Tried many configurations and tested different platform Bluetooth PAN (Personal Area Network) setups, but Bluetooth network speed remains capped at ~20 KB/s

Download complete: 2.58 MB in 206 seconds (avg 12.8 KB/s)
CONFIG_RT_LWIP_TCP_SND_BUF=8196    # 8KB transmit buffer
CONFIG_RT_LWIP_TCP_WND=8196        # 8KB receive window
CONFIG_RT_LWIP_PBUF_NUM=16         # Number of pbufs
CONFIG_RT_LWIP_TCP_SEG_NUM=40      # Number of TCP segments
CONFIG_RT_LWIP_TCPTHREAD_MBOX_SIZE=48
CONFIG_RT_LWIP_TCPTHREAD_STACKSIZE=8196
CONFIG_RT_LWIP_ETHTHREAD_STACKSIZE=8196
CONFIG_RT_LWIP_ETHTHREAD_MBOX_SIZE=48
CONFIG_RT_LWIP_USING_MQTT=y
CONFIG_RT_LWIP_USING_WEBSOCKET=y
CONFIG_LWIP_ALTCP=y
CONFIG_LWIP_ALTCP_TLS=y
CONFIG_PKG_USING_MBEDTLS=y
CONFIG_PKG_USING_MBEDTLS_USE_ALL_CERTS=y
CONFIG_PKG_USING_MBEDTLS_USER_CERTS=y
CONFIG_PKG_USING_WEBRTC=y
CONFIG_PKG_USING_WEBCLIENT=y

System DEBUG logs enabled — observing peer window size of 64154, receiver gets 1432 bytes per packet, and there’s a significant ~400ms delay between packets, which is limiting throughput

tcp_receive: window update 64154
lwip_recv_tcp: netconn_recv err=0, pbuf=0x2001c4fc
lwip_recv_tcp: buflen=72 recv_left=4018 off=1360
lwip_recv_tcp: deleting pbuf=0x2001c4fc
lwip_recv_tcp: top while sock->lastdata=0x0
lwip_recv_tcp: netconn_recv err=-7, pbuf=0x0
tcp_recved: received 1432 bytes, wnd 8196 (0).
lwip_recvfrom(0):  addr=23.225.33.154 port=80 len=1432
lwip_recvfrom(0, 0x20042246, 3946, 0x0, ..)
lwip_recv_tcp: top while sock->lastdata=0x0
tcpip_thread: PACKET 0x2001eefc
tcp_receive: window update 64154
lwip_recv_tcp: netconn_recv err=0, pbuf=0x2001c4fc
lwip_recv_tcp: buflen=1288 recv_left=3946 off=0
lwip_recv_tcp: deleting pbuf=0x2001c4fc
lwip_recv_tcp: top while sock->lastdata=0x0
lwip_recv_tcp: netconn_recv err=-7, pbuf=0x0
tcp_recved: received 1288 bytes, wnd 8196 (0).
lwip_recvfrom(0):  addr=23.225.33.154 port=80 len=1288
lwip_recvfrom(0, 0x2004274e, 2658, 0x0, ..)
lwip_recv_tcp: top while sock->lastdata=0x0
tcpip_thread: PACKET 0x2001eefc
tcp_receive: window update 64154
lwip_recv_tcp: netconn_recv err=0, pbuf=0x2001c4fc
lwip_recv_tcp: buflen=1360 recv_left=2658 off=0
lwip_recv_tcp: deleting pbuf=0x2001c4fc
lwip_recv_tcp: top while sock->lastdata=0x0
lwip_recv_tcp: netconn_recv err=-7, pbuf=0x0
tcp_recved: received 1360 bytes, wnd 8196 (0).
lwip_recvfrom(0):  addr=23.225.33.154 port=80 len=1360
lwip_recvfrom(0, 0x20042c9e, 1298, 0x0, ..)
tcpip_thread: PACKET 0x2001eefc
tcp_receive: window update 64154
lwip_recv_tcp: top while sock->lastdata=0x0
lwip_recv_tcp: netconn_recv err=0, pbuf=0x2001c4fc
lwip_recv_tcp: buflen=1360 recv_left=1298 off=0
lwip_recv_tcp: lastdata now pbuf=0x2001c4fc
tcpip_thread: PACKET 0x2001eefc
tcp_receive: window update 64154
tcp_recved: received 1298 bytes, wnd 6774 (1422).
lwip_recvfrom(0):  addr=tcpip_thread: PACKET 0x2001eefc
tcp_receive: window update 64154
23.225.33.154 port=80 len=1298
lwip_recvfrom(0, 0x200411b0, 5861, 0x0, ..)
lwip_recv_tcp: top while sock->lastdata=0x2001c4fc
lwip_recv_tcp: buflen=62 recv_left=5861 off=0
lwip_recv_tcp: deleting pbuf=0x2001c4fc
lwip_recv_tcp: top while sock->lastdata=0x0
lwip_recv_tcp: netconn_recv err=0, pbuf=0x2001ac5c
lwip_recv_tcp: buflen=1360 recv_left=5799 off=62
lwip_recv_tcp: deleting pbuf=0x2001ac5c
lwip_recv_tcp: top while sock->lastdata=0x0
lwip_recv_tcp: netconn_recv err=0, pbuf=0x2001bed4
lwip_recv_tcp: buflen=1360 recv_left=4439 off=1422
lwip_recv_tcp: deleting pbuf=0x2001bed4
lwip_recv_tcp: top while sock->lastdata=0x0
lwip_recv_tcp: netconn_recv err=-7, pbuf=0x0
tcp_recved: received 2782 bytes, wnd 8196 (0).
lwip_recvfrom(0):  addr=23.225.33.154 port=80 len=2782
lwip_recvfrom(0, 0x20041c8e, 3079, 0x0, ..)
lwip_recv_tcp: top while sock->lastdata=0x0
tcpip_thread: PACKET 0x2001eefc
tcp_receive: window update 64154
lwip_recv_tcp: netconn_recv err=0, pbuf=0x2001bed4
tcpip_thread: PACKET 0x2001eefc
tcp_receive: window update 64154
lwip_recv_tcp: buflen=1360 recv_left=3079 off=0
tcpip_thread: PACKET 0x2001eefc
tcp_receive: window update 64154
lwip_recv_tcp: deleting pbuf=0x2001bed4
lwip_recv_tcp: top while sock->lastdata=0x0
lwip_recv_tcp: netconn_recv err=0, pbuf=0x2001ac5c
lwip_recv_tcp: buflen=108 recv_left=1719 off=1360
lwip_recv_tcp: deleting pbuf=0x2001ac5c
lwip_recv_tcp: top while sock->lastdata=0x0
lwip_recv_tcp: netconn_recv err=0, pbuf=0x2001c4fc
lwip_recv_tcp: buflen=1252 recv_left=1611 off=1468
lwip_recv_tcp: deleting pbuf=0x2001c4fc
lwip_recv_tcp: top while sock->lastdata=0x0
lwip_recv_tcp: netconn_recv err=-7, pbuf=0x0
tcp_recved: received 2720 bytes, wnd 8196 (0).
lwip_recvfrom(0):  addr=23.225.33.154 port=80 len=2720
lwip_recvfrom(0, 0x2004272e, 359, 0x0, ..)
lwip_recv_tcp: top while sock->lastdata=0x0
tcp_slowtmr: processing active pcb
tcp_slowtmr: polling application
tcpip_thread: PACKET 0x2001eefc
tcp_receive: window update 64154
lwip_recv_tcp: netconn_recv err=0, pbuf=0x2001c4fc
lwip_recv_tcp: buflen=359 recv_left=359 off=0
lwip_recv_tcp: deleting pbuf=0x2001c4fc
tcp_recved: received 359 bytes, wnd 8196 (0).
lwip_recvfrom(0):  addr=23.225.33.154 port=80 len=359
[Delay Stats] Avg: 616 ms, Min: 292 ms, Max: 2544 ms, Count: 330

=== Final Delay Statistics ===
Total reads: 330
Average delay: 616 ms
Min delay: 292 ms
Max delay: 2544 ms
==============================

Is 20 KB/s already the maximum possible speed?

static int pan_download(int argc, char **argv) {
    const char *url = argv[1];
    const char *output = argv[2];
    
    // Disable Sniff mode
    bt_interface_set_sniff_enable(0);
    
    // Create session (8KB buffer)
    struct webclient_session *session = webclient_session_create(8192);
    
    // Send GET request
    int resp_status = webclient_get(session, url);
    if (resp_status != 200) {
        goto cleanup;
    }
    
    // Open output file
    int fd = open(output, O_WRONLY | O_CREAT | O_TRUNC, 0666);
    
    // Allocate buffer (8KB)
    char *buffer = rt_malloc(8192);
    
    // Download data (without yielding CPU)
    while (1) {
        int bytes_read = webclient_read(session, buffer, 8192);
        if (bytes_read <= 0) break;
        
        write(fd, buffer, bytes_read);
    }
    
cleanup:
    bt_interface_set_sniff_enable(1);  // Re-enable Sniff
    rt_free(buffer);
    close(fd);
    webclient_close(session);
    return 0;
}

Is it the same when you test with another phone?

In theory, it’s also related to the size of the package you sent.

image

I originally thought the test website shouldn’t have speed limiting, since downloads via browser were very fast, almost instant. Later, after disabling browser cache, I discovered the site actually does have throttling. I’ll run more tests later. Thanks for the clarification.