Skip to content

feat(ble): Enable Bluetooth LE Connection Subrating for split communication - #1008

Draft
tompre wants to merge 3 commits into
rmk-rs:mainfrom
tompre:subrating
Draft

feat(ble): Enable Bluetooth LE Connection Subrating for split communication#1008
tompre wants to merge 3 commits into
rmk-rs:mainfrom
tompre:subrating

Conversation

@tompre

@tompre tompre commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

As promised a few months back here is a first draft for enabling connection subrating support for the peripheral connection.

First results, with subrating factor of 30 (equal to a connection interval of 225ms):

  • Central: 50-80 uA
  • Peripheral: ~30uA

The latency of returning to 7.5ms intervals is 225ms + 2*7.5ms vs. 5-7s when using connection updates.

This means we could use sleep way more aggressively. As input lag only happens on the first keystroke.

There are a few things to improve:

@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown

Size Report

Example main PR Diff .text .data .bss
use_config/nrf52832_ble 398.7 KiB 398.7 KiB +0.00% ⬆️ +16 0 0
use_config/nrf52840_ble 448.3 KiB 448.3 KiB +0.00% ⬆️ +12 0 0
use_config/nrf52840_ble_split (central) 501.4 KiB 501.2 KiB -0.03% ⬇️ -164 0 -16
use_config/nrf52840_ble_split (peripheral) 320.5 KiB 320.5 KiB +0.00% 0 0 0
use_config/pi_pico_w_ble 672.4 KiB 672.4 KiB +0.00% ⬇️ -8 0 0
use_config/rp2040 150.4 KiB 150.4 KiB +0.00% ⬇️ -4 0 0
use_config/rp2040_split (central) 164.3 KiB 164.2 KiB -0.06% ⬇️ -88 0 -16
use_config/rp2040_split (peripheral) 27.8 KiB 27.8 KiB +0.00% 0 0 0
use_config/stm32f1 63.6 KiB 63.6 KiB +0.00% 0 0 0
use_config/stm32h7 101.9 KiB 101.9 KiB +0.00% 0 0 0
use_rust/nrf52832_ble 387.0 KiB 387.0 KiB +0.00% ⬆️ +8 0 0
use_rust/nrf52840_ble 441.9 KiB 442.0 KiB +0.00% ⬆️ +12 0 0
use_rust/nrf52840_ble_split (central) 508.0 KiB 507.9 KiB -0.01% ⬇️ -60 0 -16
use_rust/nrf52840_ble_split (peripheral) 318.4 KiB 318.4 KiB +0.00% ⬇️ -4 0 0
use_rust/pi_pico_w_ble 672.7 KiB 672.8 KiB +0.00% ⬆️ +12 0 0
use_rust/rp2040 150.2 KiB 150.2 KiB +0.00% ⬇️ -4 0 0
use_rust/rp2040_split (central) 162.7 KiB 162.8 KiB +0.01% ⬆️ +44 0 -16
use_rust/rp2040_split (peripheral) 28.2 KiB 28.2 KiB +0.00% 0 0 0
use_rust/stm32f1 63.5 KiB 63.5 KiB +0.00% 0 0 0
use_rust/stm32h7 121.8 KiB 121.8 KiB +0.00% ⬇️ -4 0 0
use_config/nrf52832_ble — 398.7 KiB → 398.7 KiB (+0.00% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 364584	   8620	  35056	 408260	  63ac4	rmk-nrf52832

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 364568	   8620	  35056	 408244	  63ab4	rmk-nrf52832

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%     +32  [ = ]       0    .symtab
  +0.0%     +16  [ = ]       0    .debug_frame
  +0.0%     +16  +0.0%     +16    .text
   +29%     +13  [ = ]       0    [Unmapped]
  +0.0%      +8  [ = ]       0    .debug_aranges
  +0.0%      +8  [ = ]       0    .debug_ranges
  -0.0%      -1  [ = ]       0    .strtab
  -0.7%     -54  [ = ]       0    .debug_abbrev
  -0.1%    -213  [ = ]       0    .debug_line
  -0.0%    -220  [ = ]       0    .debug_str
  -0.0%    -897  [ = ]       0    .debug_info
  -0.0% -1.26Ki  +0.0%     +16    TOTAL
use_config/nrf52840_ble — 448.3 KiB → 448.3 KiB (+0.00% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 397312	   8628	  53168	 459108	  70164	rmk-nrf52840

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 397300	   8628	  53168	 459096	  70158	rmk-nrf52840

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%     +33  [ = ]       0    .debug_info
  +0.0%     +31  [ = ]       0    .debug_str
  +0.0%     +19  [ = ]       0    .strtab
  +0.0%     +16  [ = ]       0    .debug_frame
  +0.0%     +15  [ = ]       0    .debug_line
  +0.0%     +12  +0.0%     +12    .text
  +0.0%      +8  [ = ]       0    .debug_aranges
  +0.0%      +8  [ = ]       0    .debug_ranges
 -13.7%     -10  [ = ]       0    [Unmapped]
  +0.0%    +132  +0.0%     +12    TOTAL
use_config/nrf52840_ble_split (central) — 501.4 KiB → 501.2 KiB (-0.03% ⬇️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 454608	   8684	  49960	 513252	  7d4e4	central

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 454772	   8684	  49976	 513432	  7d598	central

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1%    +160  [ = ]       0    .symtab
  +0.0%    +140  [ = ]       0    .strtab
  +0.1%     +80  [ = ]       0    .debug_frame
  +0.1%     +40  [ = ]       0    .debug_aranges
  +6.1%      +3  [ = ]       0    [Unmapped]
  -0.0%      -4  -0.0%      -4    .rodata
  [ = ]       0  -0.0%     -16    .bss
  -0.5%     -39  [ = ]       0    .debug_abbrev
  -0.0%    -160  -0.0%    -160    .text
  -0.1%    -233  [ = ]       0    .debug_line
  -0.0%    -233  [ = ]       0    .debug_loc
  -0.2%    -544  [ = ]       0    .debug_ranges
  -0.0%    -887  [ = ]       0    .debug_info
  -0.1% -3.67Ki  [ = ]       0    .debug_str
  -0.1% -5.31Ki  -0.0%    -180    TOTAL
use_config/nrf52840_ble_split (peripheral) — 320.5 KiB → 320.5 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 292264	   8500	  27464	 328228	  50224	peripheral

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 292264	   8500	  27464	 328228	  50224	peripheral

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%      +3  [ = ]       0    .debug_str
  +0.0%      +1  [ = ]       0    .debug_info
  -0.0%      -4  [ = ]       0    .strtab
  [ = ]       0  [ = ]       0    TOTAL
use_config/pi_pico_w_ble — 672.4 KiB → 672.4 KiB (+0.00% ⬇️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 634268	      0	  54304	 688572	  a81bc	rmk-pi-pico-w

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 634276	      0	  54304	 688580	  a81c4	rmk-pi-pico-w

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%     +16  [ = ]       0    .debug_info
   +26%     +11  [ = ]       0    [Unmapped]
  +0.0%      +3  [ = ]       0    .strtab
  -0.0%      -4  -0.0%      -4    .rodata
  -0.0%      -4  -0.0%      -4    .text
  -0.0%      -5  [ = ]       0    .debug_line
  -0.0%      -9  [ = ]       0    .debug_str
  +0.0%      +8  -0.0%      -8    TOTAL
use_config/rp2040 — 150.4 KiB → 150.4 KiB (+0.00% ⬇️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 138376	      0	  15644	 154020	  259a4	rmk-rp2040

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 138380	      0	  15644	 154024	  259a8	rmk-rp2040

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%     +72  [ = ]       0    .debug_str
  +0.0%      +8  [ = ]       0    .strtab
  -0.0%      -4  -0.0%      -4    .text
  -0.0%      -9  [ = ]       0    .debug_info
 -38.2%     -26  [ = ]       0    [Unmapped]
  -0.0%     -49  [ = ]       0    .debug_line
  -0.0%      -8  -0.0%      -4    TOTAL
use_config/rp2040_split (central) — 164.3 KiB → 164.2 KiB (-0.06% ⬇️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 151604	      0	  16492	 168096	  290a0	central

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 151692	      0	  16508	 168200	  29108	central

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.4%    +128  [ = ]       0    .symtab
  +0.0%     +28  [ = ]       0    .strtab
   +57%     +21  [ = ]       0    [Unmapped]
  [ = ]       0  -0.1%     -16    .bss
  -0.1%     -88  -0.1%     -88    .text
  -0.1%    -116  [ = ]       0    .debug_line
  -0.0%    -380  [ = ]       0    .debug_info
  -0.5%    -488  [ = ]       0    .debug_ranges
  -0.2%    -719  [ = ]       0    .debug_loc
  -0.1% -1.11Ki  [ = ]       0    .debug_str
  -0.1% -2.69Ki  -0.1%    -104    TOTAL
use_config/rp2040_split (peripheral) — 27.8 KiB → 27.8 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
  25616	     60	   2796	  28472	   6f38	peripheral

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
  25616	     60	   2796	  28472	   6f38	peripheral

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1%    +707  [ = ]       0    .debug_str
  +0.2%     +41  [ = ]       0    .strtab
 -10.5%      -4  [ = ]       0    [Unmapped]
  +0.1%    +744  [ = ]       0    TOTAL
use_config/stm32f1 — 63.6 KiB → 63.6 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
  57588	     28	   7488	  65104	   fe50	rmk-stm32f1

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
  57588	     28	   7488	  65104	   fe50	rmk-stm32f1

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  [ = ]       0  [ = ]       0    TOTAL
use_config/stm32h7 — 101.9 KiB → 101.9 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
  94304	    264	   9736	 104304	  19770	rmk-stm32h7

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
  94304	    264	   9736	 104304	  19770	rmk-stm32h7

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  -0.3%    -188  [ = ]       0    .strtab
  -0.1% -1.23Ki  [ = ]       0    .debug_str
  -0.0% -1.41Ki  [ = ]       0    TOTAL
use_rust/nrf52832_ble — 387.0 KiB → 387.0 KiB (+0.00% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 352600	   8620	  35112	 396332	  60c2c	rmk-nrf52832

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 352592	   8620	  35112	 396324	  60c24	rmk-nrf52832

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%     +36  [ = ]       0    .debug_info
  +0.0%     +32  [ = ]       0    .symtab
  +0.0%     +27  [ = ]       0    .strtab
  +0.0%     +16  [ = ]       0    .debug_frame
  +0.0%     +16  [ = ]       0    .debug_str
  +0.0%     +14  [ = ]       0    .debug_line
  +0.0%      +8  [ = ]       0    .debug_aranges
  +0.0%      +8  [ = ]       0    .debug_ranges
  +0.0%      +8  +0.0%      +8    .text
 -11.3%      -6  [ = ]       0    [Unmapped]
  -0.0%    -103  [ = ]       0    .debug_loc
  +0.0%     +56  +0.0%      +8    TOTAL
use_rust/nrf52840_ble — 441.9 KiB → 442.0 KiB (+0.00% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 396708	   8628	  47224	 452560	  6e7d0	rmk-nrf52840

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 396696	   8628	  47224	 452548	  6e7c4	rmk-nrf52840

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%     +16  [ = ]       0    .debug_frame
  +0.0%     +12  +0.0%     +12    .text
  +0.0%      +8  [ = ]       0    .debug_aranges
  +0.0%      +8  [ = ]       0    .debug_ranges
  -0.0%     -10  [ = ]       0    .debug_loc
  -0.0%     -11  [ = ]       0    .strtab
 -16.7%     -11  [ = ]       0    [Unmapped]
  -0.0%     -27  [ = ]       0    .debug_info
  -0.0%     -88  [ = ]       0    .debug_str
  -0.1%    -313  [ = ]       0    .debug_line
  -0.0%    -416  +0.0%     +12    TOTAL
use_rust/nrf52840_ble_split (central) — 508.0 KiB → 507.9 KiB (-0.01% ⬇️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 457496	   8684	  53960	 520140	  7efcc	central

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 457556	   8684	  53976	 520216	  7f018	central

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%     +45  [ = ]       0    .strtab
  +0.0%     +32  [ = ]       0    .symtab
  +0.0%     +16  [ = ]       0    .debug_frame
  +0.0%      +8  [ = ]       0    .debug_aranges
 -15.7%      -8  [ = ]       0    [Unmapped]
  [ = ]       0  -0.0%     -16    .bss
  -0.5%     -39  [ = ]       0    .debug_abbrev
  -0.0%     -60  -0.0%     -60    .text
  -0.1%    -210  [ = ]       0    .debug_line
  -0.1%    -451  [ = ]       0    .debug_loc
  -0.2%    -552  [ = ]       0    .debug_ranges
  -0.0%    -796  [ = ]       0    .debug_info
  -0.0% -2.18Ki  [ = ]       0    .debug_str
  -0.0% -4.14Ki  -0.0%     -76    TOTAL
use_rust/nrf52840_ble_split (peripheral) — 318.4 KiB → 318.4 KiB (+0.00% ⬇️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 290264	   8500	  27232	 325996	  4f96c	peripheral

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 290268	   8500	  27232	 326000	  4f970	peripheral

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%    +235  [ = ]       0    .debug_info
  +0.0%    +126  [ = ]       0    .debug_str
  +0.0%     +97  [ = ]       0    .debug_line
  +3.0%      +2  [ = ]       0    [Unmapped]
  -0.0%      -4  -0.0%      -4    .text
  -0.0%     -16  [ = ]       0    .strtab
  +0.0%    +440  -0.0%      -4    TOTAL
use_rust/pi_pico_w_ble — 672.7 KiB → 672.8 KiB (+0.00% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 634404	      0	  54496	 688900	  a8304	rmk-pi-pico-w

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 634392	      0	  54496	 688888	  a82f8	rmk-pi-pico-w

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%      +8  +0.0%      +8    .text
  +0.0%      +4  +0.0%      +4    .rodata
 -15.4%      -8  [ = ]       0    [Unmapped]
  -0.0%     -10  [ = ]       0    .debug_loc
  -0.0%     -23  [ = ]       0    .strtab
  -0.4%     -39  [ = ]       0    .debug_abbrev
  -0.0%    -109  [ = ]       0    .debug_line
  -0.0%    -189  [ = ]       0    .debug_str
  -0.0%    -230  [ = ]       0    .debug_info
  -0.0%    -596  +0.0%     +12    TOTAL
use_rust/rp2040 — 150.2 KiB → 150.2 KiB (+0.00% ⬇️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 138196	      0	  15564	 153760	  258a0	rmk-rp2040

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 138200	      0	  15564	 153764	  258a4	rmk-rp2040

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%     +73  [ = ]       0    .debug_str
  +0.0%      +8  [ = ]       0    .strtab
  +8.6%      +5  [ = ]       0    [Unmapped]
  -0.0%      -4  -0.0%      -4    .text
  -0.0%      -9  [ = ]       0    .debug_info
  -0.0%     -10  [ = ]       0    .debug_loc
  -0.0%     -47  [ = ]       0    .debug_line
  +0.0%     +16  -0.0%      -4    TOTAL
use_rust/rp2040_split (central) — 162.7 KiB → 162.8 KiB (+0.01% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 150348	      0	  16324	 166672	  28b10	central

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 150304	      0	  16340	 166644	  28af4	central

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.2%    +184  [ = ]       0    .debug_ranges
  +0.0%     +44  +0.0%     +44    .text
  -0.0%      -6  [ = ]       0    .strtab
  [ = ]       0  -0.1%     -16    .bss
 -32.7%     -16  [ = ]       0    [Unmapped]
  -0.1%     -32  [ = ]       0    .symtab
  -0.0%     -33  [ = ]       0    .debug_line
  -0.1%    -297  [ = ]       0    .debug_loc
  -0.1%    -823  [ = ]       0    .debug_info
  -0.1% -2.00Ki  [ = ]       0    .debug_str
  -0.1% -2.96Ki  +0.0%     +28    TOTAL
use_rust/rp2040_split (peripheral) — 28.2 KiB → 28.2 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
  25716	     60	   3060	  28836	   70a4	peripheral

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
  25716	     60	   3060	  28836	   70a4	peripheral

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%      +2  [ = ]       0    .strtab
  +1.6%      +1  [ = ]       0    [Unmapped]
  -0.0%      -3  [ = ]       0    .debug_str
  [ = ]       0  [ = ]       0    TOTAL
use_rust/stm32f1 — 63.5 KiB → 63.5 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
  57536	     28	   7504	  65068	   fe2c	rmk-stm32f1

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
  57536	     28	   7504	  65068	   fe2c	rmk-stm32f1

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  [ = ]       0  [ = ]       0    TOTAL
use_rust/stm32h7 — 121.8 KiB → 121.8 KiB (+0.00% ⬇️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 108516	    320	  15852	 124688	  1e710	rmk-stm32h7

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 108520	    320	  15852	 124692	  1e714	rmk-stm32h7

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1%    +124  [ = ]       0    .debug_line
  +0.0%     +37  [ = ]       0    .debug_info
   +15%      +6  [ = ]       0    [Unmapped]
  -0.0%      -4  -0.0%      -4    .text
  -0.2%    -182  [ = ]       0    .strtab
  -0.1% -2.00Ki  [ = ]       0    .debug_str
  -0.0% -2.02Ki  -0.0%      -4    TOTAL

@HaoboGu

HaoboGu commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator

#886 introduced a fast polling loop (5ms) which leads to 500-700uA of current draw in central. We should fix that anyway I think.

Yes, the fix looks fine

I changed Central max latency to be similarly long as the subrating. I'm unsure what this does with OS support.

I don't see any issue max_latency = 30

SplitMessage gatt messages always use the full buffer rather than only sending the encoded data, sending only the data might allow for faster resets of the subrate factor, if this was not done on purpose?

Yeah, only encoded buffer should be sent, that needs a fix. to_slice returns the encoded buf so the fix is easy.

The result is quite impressive! Thanks a lot for your effort!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants