Skip to content

feat: use rmk-boot.x linker script for DFU partition layout - #1018

Open
Schievel1 wants to merge 2 commits into
rmk-rs:mainfrom
Schievel1:auto-flash-layout
Open

feat: use rmk-boot.x linker script for DFU partition layout#1018
Schievel1 wants to merge 2 commits into
rmk-rs:mainfrom
Schievel1:auto-flash-layout

Conversation

@Schievel1

@Schievel1 Schievel1 commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

This PR should simplify the process of setting the right flash layout when using rmk-boot.
The calculation formula is still the same (flash size - what the bootloader takes up - storage = rest. ACTIVE = rest/2 - 1 page, DFU = rest/2 + 1 page) and rmk-boot's build.rs creates a memory.x accordingly. Additionally it should create a rmk-boot.x with the matching flash layout of the (RMK-)application + a few linker symbols that the application can use to initialize the flash and its partitions.
e.g. a rmk-boot.x looks like this:

MEMORY {
  FLASH : ORIGIN = 0x10007000, LENGTH = 966656   /* absolute XIP, where your firmware lives */
  RAM   : ORIGIN = 0x20000000, LENGTH = 256K
}

__rmk_boot_state_offset   = 0x6000;   /* flash-relative, consumed at runtime */
__rmk_boot_state_size     = 0x1000;
__rmk_boot_dfu_offset     = 0xF3000;
__rmk_boot_dfu_size       = 0xED000;
__rmk_boot_storage_offset = 0x1E0000;

rmk-boot not only creates that rmk-boot.x at build, it also provides matching rmk-boot.x-files for its pre-built variants. (rmk-boot-rp2040-16mb.x for example)

The users build.rs then uses that rmk-boot.x if it exists in the project directory instead of a memory.x. It creates a memory.x from it and both get fed to the linker.
The users code can then use rmk::dfu::init_flash_from_linkerscript() instead of rmk::dfu::init_flash() to partition the flash without giving any offsets and sizes. For use_config this happens automatically.

If users do provide dfu_offset, dfu_size etc. in the [dfu] section of the keyboard.toml, init_flash() is used instead and the linker symbols are ignored. For use_rust keyboards users can use init_flash() directly for that. This way users can still go wild with their flash setup if they want something completely different.

Related PRs:
rmk-rs/rmk-template#26
rmk-rs/rmk-boot#2

@HaoboGu

HaoboGu commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

The symbol existence is checked in rmk when bootloader feature like rmk-boot is enabled. This means that if rmk-boot is defined, the user should either define their own __rmk_boot* symbols in their linkerscript or use rmk-boot.x.

And I think it should not be overwritten by keyboard.toml. Let user define their layout in their linker script is better imo, because I think 99% users won't do it. That makes the configuration cleaner.

The last point from me is the storage size, default 128KB is a little bit more. For example, nRF52833 has only 512KB flash(I just realized that it's impossible to use rmk-boot on it). I want it to be tunable, or default to 32KB.

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

Size Report

Example main PR Diff .text .data .bss
use_config/nrf52832_ble 397.9 KiB 397.9 KiB +0.00% ⬇️ -4 0 0
use_config/nrf52840_ble 439.1 KiB 439.0 KiB -0.01% ⬇️ -60 0 0
use_config/nrf52840_ble_split (central) 501.6 KiB 501.6 KiB +0.00% 0 0 0
use_config/nrf52840_ble_split (peripheral) 320.9 KiB 321.1 KiB +0.04% ⬆️ +164 0 0
use_config/pi_pico_w_ble 671.8 KiB 671.8 KiB +0.00% 0 0 0
use_config/rp2040 146.2 KiB 146.2 KiB +0.00% 0 0 0
use_config/rp2040_split (central) 159.7 KiB 159.7 KiB +0.00% 0 0 0
use_config/rp2040_split (peripheral) 27.9 KiB 27.9 KiB +0.00% 0 0 0
use_config/stm32f1 62.6 KiB 62.6 KiB +0.00% 0 0 0
use_config/stm32h7 100.8 KiB 100.8 KiB +0.00% 0 0 0
use_rust/nrf52832_ble 386.2 KiB 386.2 KiB +0.00% 0 0 0
use_rust/nrf52840_ble 436.0 KiB 436.0 KiB +0.00% ⬇️ -4 0 0
use_rust/nrf52840_ble_split (central) 505.2 KiB 505.2 KiB +0.00% 0 0 0
use_rust/nrf52840_ble_split (peripheral) 318.9 KiB 318.9 KiB +0.00% 0 0 0
use_rust/pi_pico_w_ble 671.6 KiB 671.6 KiB +0.00% ⬇️ -12 0 0
use_rust/rp2040 145.5 KiB 145.5 KiB +0.00% 0 0 0
use_rust/rp2040_split (central) 158.2 KiB 158.2 KiB +0.00% 0 0 0
use_rust/rp2040_split (peripheral) 28.2 KiB 28.2 KiB +0.00% 0 0 0
use_rust/stm32f1 61.8 KiB 61.8 KiB +0.00% ⬇️ -4 0 0
use_rust/stm32h7 119.6 KiB 119.6 KiB +0.00% 0 0 0
use_config/nrf52832_ble — 397.9 KiB → 397.9 KiB (+0.00% ⬇️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 365452	   8620	  33352	 407424	  63780	rmk-nrf52832

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 365456	   8620	  33352	 407428	  63784	rmk-nrf52832

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%     +12  [ = ]       0    .debug_loc
  +8.0%      +4  [ = ]       0    [Unmapped]
  -0.0%      -4  -0.0%      -4    .text
  +0.0%     +12  -0.0%      -4    TOTAL
use_config/nrf52840_ble — 439.1 KiB → 439.0 KiB (-0.01% ⬇️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 397564	   8628	  43376	 449568	  6dc20	rmk-nrf52840

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 397624	   8628	  43376	 449628	  6dc5c	rmk-nrf52840

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.5%     +39  [ = ]       0    .debug_abbrev
  -2.9%      -2  [ = ]       0    [Unmapped]
  -0.1%     -24  [ = ]       0    .debug_aranges
  -0.1%     -48  [ = ]       0    .debug_frame
  -0.0%     -60  -0.0%     -60    .text
  -0.0%     -88  [ = ]       0    .debug_ranges
  -0.1%     -96  [ = ]       0    .symtab
  -0.0%    -102  [ = ]       0    .strtab
  -0.0%    -164  [ = ]       0    .debug_str
  -0.0%    -234  [ = ]       0    .debug_loc
  -0.0%    -379  [ = ]       0    .debug_info
  -0.1%    -446  [ = ]       0    .debug_line
  -0.0% -1.57Ki  -0.0%     -60    TOTAL
use_config/nrf52840_ble_split (central) — 501.6 KiB → 501.6 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 456364	   8684	  48544	 513592	  7d638	central

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 456364	   8684	  48544	 513592	  7d638	central

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +1.8%      +1  [ = ]       0    [Unmapped]
  -0.0%     -13  [ = ]       0    .debug_loc
  -0.0%     -12  [ = ]       0    TOTAL
use_config/nrf52840_ble_split (peripheral) — 320.9 KiB → 321.1 KiB (+0.04% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 292880	   8500	  27424	 328804	  50464	peripheral

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 292716	   8500	  27424	 328640	  503c0	peripheral

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1%    +164  +0.1%    +164    .text
  +0.1%    +112  [ = ]       0    .debug_ranges
  +0.0%     +88  [ = ]       0    .debug_line
  -4.1%      -2  [ = ]       0    [Unmapped]
  -0.1%     -24  [ = ]       0    .debug_aranges
  -0.0%     -40  [ = ]       0    .debug_info
  -0.1%     -48  [ = ]       0    .debug_frame
  -0.0%     -91  [ = ]       0    .strtab
  -0.1%     -96  [ = ]       0    .symtab
  -0.0%     -98  [ = ]       0    .debug_str
  -0.1%    -533  [ = ]       0    .debug_loc
  -0.0%    -568  +0.0%    +164    TOTAL
use_config/pi_pico_w_ble — 671.8 KiB → 671.8 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 635008	      0	  52904	 687912	  a7f28	rmk-pi-pico-w

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 635008	      0	  52904	 687912	  a7f28	rmk-pi-pico-w

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%    +222  [ = ]       0    .debug_info
  +0.0%     +24  [ = ]       0    .debug_line
  +0.0%      +9  [ = ]       0    .debug_loc
  +6.1%      +3  [ = ]       0    [Unmapped]
  -0.0%      -3  [ = ]       0    .strtab
  -0.0%     -15  [ = ]       0    .debug_str
  +0.0%    +240  [ = ]       0    TOTAL
use_config/rp2040 — 146.2 KiB → 146.2 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 135788	      0	  13892	 149680	  248b0	rmk-rp2040

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 135788	      0	  13892	 149680	  248b0	rmk-rp2040

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.2%    +516  [ = ]       0    .debug_loc
  +0.0%     +72  [ = ]       0    .debug_str
  +0.0%      +8  [ = ]       0    .strtab
  +0.0%      +7  [ = ]       0    .debug_info
  +5.3%      +2  [ = ]       0    [Unmapped]
  -0.0%     -77  [ = ]       0    .debug_line
  +0.0%    +528  [ = ]       0    TOTAL
use_config/rp2040_split (central) — 159.7 KiB → 159.7 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 148744	      0	  14828	 163572	  27ef4	central

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 148744	      0	  14828	 163572	  27ef4	central

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  -7.1%      -3  [ = ]       0    [Unmapped]
  -0.0%      -5  [ = ]       0    .strtab
  -0.0%     -48  [ = ]       0    .debug_info
  -0.0%    -105  [ = ]       0    .debug_str
  -0.1%    -135  [ = ]       0    .debug_line
  -0.1%    -200  [ = ]       0    .debug_loc
  -0.0%    -496  [ = ]       0    TOTAL
use_config/rp2040_split (peripheral) — 27.9 KiB → 27.9 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
  25696	     60	   2804	  28560	   6f90	peripheral

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
  25696	     60	   2804	  28560	   6f90	peripheral

Bloaty diff (PR vs main):

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

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
  57688	     28	   6336	  64052	   fa34	rmk-stm32f1

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
  57688	     28	   6336	  64052	   fa34	rmk-stm32f1

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +1.7%      +1  [ = ]       0    [Unmapped]
  -0.0%      -1  [ = ]       0    .debug_str
  [ = ]       0  [ = ]       0    TOTAL
use_config/stm32h7 — 100.8 KiB → 100.8 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
  94844	    264	   8112	 103220	  19334	rmk-stm32h7

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
  94844	    264	   8112	 103220	  19334	rmk-stm32h7

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  [ = ]       0  [ = ]       0    TOTAL
use_rust/nrf52832_ble — 386.2 KiB → 386.2 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 353496	   8620	  33328	 395444	  608b4	rmk-nrf52832

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 353496	   8620	  33328	 395444	  608b4	rmk-nrf52832

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  -4.5%      -2  [ = ]       0    [Unmapped]
  -0.0%     -10  [ = ]       0    .debug_loc
  -0.0%     -12  [ = ]       0    TOTAL
use_rust/nrf52840_ble — 436.0 KiB → 436.0 KiB (+0.00% ⬇️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 397216	   8628	  40624	 446468	  6d004	rmk-nrf52840

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 397220	   8628	  40624	 446472	  6d008	rmk-nrf52840

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +7.0%      +4  [ = ]       0    [Unmapped]
  -0.0%      -4  -0.0%      -4    .text
  -0.0%     -10  [ = ]       0    .debug_loc
  -0.0%     -70  [ = ]       0    .debug_line
  -0.0%     -80  -0.0%      -4    TOTAL
use_rust/nrf52840_ble_split (central) — 505.2 KiB → 505.2 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 458088	   8684	  50512	 517284	  7e4a4	central

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 458088	   8684	  50512	 517284	  7e4a4	central

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%     +12  [ = ]       0    .debug_loc
  -1.6%      -1  [ = ]       0    [Unmapped]
  -0.0%     -12  [ = ]       0    .strtab
  -0.0%     -44  [ = ]       0    .debug_str
  -0.0%     -48  [ = ]       0    .debug_info
  -0.0%    -131  [ = ]       0    .debug_line
  -0.0%    -224  [ = ]       0    TOTAL
use_rust/nrf52840_ble_split (peripheral) — 318.9 KiB → 318.9 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 290876	   8500	  27192	 326568	  4fba8	peripheral

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 290876	   8500	  27192	 326568	  4fba8	peripheral

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%     +12  [ = ]       0    .debug_loc
  +0.0%      +2  [ = ]       0    .debug_info
  -0.0%      -1  [ = ]       0    .debug_line
  -1.5%      -1  [ = ]       0    [Unmapped]
  -0.0%     -16  [ = ]       0    .strtab
  -0.0%     -32  [ = ]       0    .debug_str
  -0.0%     -36  [ = ]       0    TOTAL
use_rust/pi_pico_w_ble — 671.6 KiB → 671.6 KiB (+0.00% ⬇️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 634704	      0	  53008	 687712	  a7e60	rmk-pi-pico-w

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 634716	      0	  53008	 687724	  a7e6c	rmk-pi-pico-w

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
   +21%     +12  [ = ]       0    [Unmapped]
  -0.0%     -12  -0.0%     -12    .text
  [ = ]       0  -0.0%     -12    TOTAL
use_rust/rp2040 — 145.5 KiB → 145.5 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 135288	      0	  13732	 149020	  2461c	rmk-rp2040

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 135288	      0	  13732	 149020	  2461c	rmk-rp2040

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  -3.6%      -2  [ = ]       0    [Unmapped]
  -0.0%     -10  [ = ]       0    .debug_loc
  -0.0%     -44  [ = ]       0    .debug_line
  -0.0%     -56  [ = ]       0    TOTAL
use_rust/rp2040_split (central) — 158.2 KiB → 158.2 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 147476	      0	  14572	 162048	  27900	central

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 147476	      0	  14572	 162048	  27900	central

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.2% +4.42Ki  [ = ]       0    .debug_str
  +0.4%    +522  [ = ]       0    .strtab
  -6.5%      -4  [ = ]       0    [Unmapped]
  -0.0%     -25  [ = ]       0    .debug_info
  -0.1%    -106  [ = ]       0    .debug_line
  +0.1% +4.80Ki  [ = ]       0    TOTAL
use_rust/rp2040_split (peripheral) — 28.2 KiB → 28.2 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
  25796	     60	   3068	  28924	   70fc	peripheral

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
  25796	     60	   3068	  28924	   70fc	peripheral

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1%    +586  [ = ]       0    .debug_str
  +0.1%     +28  [ = ]       0    .strtab
  +4.0%      +2  [ = ]       0    [Unmapped]
  +0.0%    +616  [ = ]       0    TOTAL
use_rust/stm32f1 — 61.8 KiB → 61.8 KiB (+0.00% ⬇️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
  57012	     28	   6272	  63312	   f750	rmk-stm32f1

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
  57016	     28	   6272	  63316	   f754	rmk-stm32f1

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%     +62  [ = ]       0    .debug_str
  +0.0%      +9  [ = ]       0    .strtab
  +0.0%      +6  [ = ]       0    .debug_line
  +5.0%      +3  [ = ]       0    [Unmapped]
  -0.0%      -4  -0.0%      -4    .text
  +0.0%     +76  -0.0%      -4    TOTAL
use_rust/stm32h7 — 119.6 KiB → 119.6 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 108172	    320	  14012	 122504	  1de88	rmk-stm32h7

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 108172	    320	  14012	 122504	  1de88	rmk-stm32h7

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  -0.0%      -1  [ = ]       0    .debug_str
  -0.0%      -1  [ = ]       0    .strtab
  -0.0%     -10  [ = ]       0    .debug_loc
  -0.0%     -12  [ = ]       0    TOTAL

…_flash_from_linkerscript

Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
@Schievel1

Copy link
Copy Markdown
Contributor Author

The symbol existence is checked in rmk when bootloader feature like rmk-boot is enabled. This means that if rmk-boot is defined, the user should either define their own __rmk_boot* symbols in their linkerscript or use rmk-boot.x.

And I think it should not be overwritten by keyboard.toml. Let user define their layout in their linker script is better imo, because I think 99% users won't do it. That makes the configuration cleaner.

The last point from me is the storage size, default 128KB is a little bit more. For example, nRF52833 has only 512KB flash(I just realized that it's impossible to use rmk-boot on it). I want it to be tunable, or default to 32KB.

for now I prefer to bind everything bootloader related to the dfu feature, since this is the only benefit we get at the moment with rmk-boot. There is not other reason to use it. As we spoke on discord, I will try and make bootloader versions that don't have DFU partitions and the failsafe swap, then we can split a new rmk-boot feature off of dfu.

The offsets and sizes are now bound to symbols defined in rmk-boot.x. This file is created by rmk-boot at built. The pre-built binaries come with pre-created rmx-boot.x, that the user copies in their project dir instead of a memory.x.
keyboard.toml can't change that layout anymore, instead when users want to roll their own bootloader, their have to define the offsets in their linker script and link with it.

Storage size is not easily changeable in RMK when using embassy-boot, because when changing the storage size (offset) this also changes the size of the ACTIVE and DFU partitions. So you end up with new sizes and offsets for them as well. I tuned down the default to 32K and in rmk-boot I added the possibility to easily change the storage size. Then users just need to do change that, build rmk-boot, flash it and copy the rmk-boot.x into their project to change the storage size.

println!("cargo:rustc-link-search={}", out.display());
println!("cargo:rerun-if-changed=memory.x");

if Path::new("rmk-boot.x").exists() {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer to have rmk-boot.x in rmk-boot project only and keep memory.x. When users want to use rmk-boot, just add 1 line like:

println!("cargo:rustc-link-arg=-Trmk-boot.x");

This is the pattern of many Rust embedded projects, like cortex-m-rt, defmt. I don't know if it's possible for rmk-boot. I prefer this way if it's possible.

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