Skip to content

feat(dfu_split): Embassy boot flash peripheral from central #886

Open
Schievel1 wants to merge 1 commit into
HaoboGu:mainfrom
Schievel1:embassy-boot-flash-peripheral
Open

feat(dfu_split): Embassy boot flash peripheral from central #886
Schievel1 wants to merge 1 commit into
HaoboGu:mainfrom
Schievel1:embassy-boot-flash-peripheral

Conversation

@Schievel1

@Schievel1 Schievel1 commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

This is a follow up PR for #877 which uses embassy-boot to flash the peripheral through the central.

The idea is to minimize the effort of flashing. #877 ensures, that we don't need to open up the keyboard and press the boot0 button to get the RP2040 into bootloader. It is enough to run dfu-util on the host to flash it.
This PR takes this idea further. We embed the peripheral's firmware into the centrals firmware, then during startup of the central, we ask peripheral for it's current firmware CRC. Central calculates the CRC of it's embedded peripheral firmware. If they don't match, peripheral has an old firmware and central needs to flash it.
It then proceeds sending chunks which peripheral puts into its DFU partition, when done central makes this known to the peripheral. Then peripheral resets.
After that this is normal embassy-boot bootloader flash, it copies DFU to ACTIVE, boots it, if it booted, good, if not embassy-boot does a rollback. (That rollback thing is important, because it means we can try again flashing a working firmware without the need to take the keyboard apart).
After boot the peripherals firmware CRCs on central and peripheral (hopefully) match, and we don't flash the peripheral again.

If peripheral misses the central asking for its firmwares CRC (e.g. starts after central) it would not get an update. Therefore we let peripheral send it's firmares CRC proactively at every start and central reacts to it accordingly.

This obviously needs enough flash space on the central to hold the peripherals firmware.

additionally we can use the central as a relay for updating the peripheral via dfu. This uses the altsetting of DFU. (usually this is used to flash different areas of the flash of a chip instead of different chips)
When we run dfu-util -D ./central.bin -a 0 we flash the central. If we run dfu-util -D ./peripheral.bin -a 1 we can flash the peripheral even though only the central is plugged in the host's USB.
For several peripherals we can specify -a 2, -a 3 etc.

The diagram below shows that we check the CRC of every chunk we send, send it to central and wait for an ack before continuing. Of course this could be optimized (for example with a window of 20 chunks that we check the CRC of and so on) but this flashes the examples peripheral firmware (~34kB) via the central as a relay in <4s. I think this is good enough for now.

Currently only supports serial connection. I experiment with bluetooth still, but couldn't get in to work properly.

Example logs:
Peripheral running, central starts up and has newer peripheral firmware:

[INFO ] RMK start! (central RMKRP2040embassy-split/src/central.rs:44)
[INFO ] Flash layout: state @ 0x6000 (4K), active @ 0x7000 (944K), dfu @ 0xF3000 (948K), storage @ 0x1E0000 (128K) (central RMKRP2040embassy-split/src/central.rs:83)
[INFO ] Flash capacity 128 KB, RMK use 128 KB(32 sectors) starting from 0x0 as storage (rmk src/storage/mod.rs:434)
[INFO ] Device enabled (rmk src/usb/mod.rs:451)
[INFO ] Running peripheral manager 0 (rmk split/serial/mod.rs:27)
[INFO ] dfu_split: checking peripheral firmware... (rmk src/split/driver.rs:201)
[INFO ] Device suspended, the Vbus current limit is 500µA (or 2.5mA for high-power devices with remote wakeup enabled). (rmk src/usb/mod.rs:490)
[INFO ] dfu_split: firmware hash mismatch (peripheral=0x2112eded, expected=0x6938687c), starting update (31360 bytes) (rmk src/split/driver.rs:245) <-- new peripheral firmware in central, needs to flash 
[INFO ] dfu_split: sending chunk at offset 0 (256 bytes) (rmk src/split/driver.rs:276)
[INFO ] dfu_split: sending chunk at offset 256 (256 bytes) (rmk src/split/driver.rs:276)
[INFO ] dfu_split: sending chunk at offset 512 (256 bytes) (rmk src/split/driver.rs:276)
... chunks keep coming
[INFO ] dfu_split: sending chunk at offset 30976 (256 bytes) (rmk src/split/driver.rs:276)
[INFO ] dfu_split: sending chunk at offset 31232 (64 bytes) (rmk src/split/driver.rs:276)
[INFO ] dfu_split: all chunks sent, signaling update complete (rmk src/split/driver.rs:312)
[INFO ] dfu_split: peripheral confirmed, update complete (rmk src/split/driver.rs:323)
[WARN ] Framing error (embassy_rp src/uart/buffered.rs:538) <- Peripheral resets itself
[WARN ] Break error (embassy_rp src/uart/buffered.rs:544)
[ERROR] Peripheral message read error: SerialError (rmk src/split/driver.rs:146)
[INFO ] dfu_split: proactive hash from peripheral (0x2112eded), checking... (rmk src/split/driver.rs:171) <- peripheral starts up with new firmware
[INFO ] dfu_split: peripheral firmware hash matches (0x2112eded), no update needed (rmk src/split/driver.rs:176) <- firmware CRCs match now, no update. 

Central runnnig, peripheral starts up:

[INFO ] Device suspended, the Vbus current limit is 500µA (or 2.5mA for high-power devices with remote wakeup enabled). (rmk src/usb/mod.rs:490)
[ERROR] Peripheral message read error: SerialError (rmk src/split/driver.rs:146)
[INFO ] dfu_split: proactive hash from peripheral (0x6938687c), checking... (rmk src/split/driver.rs:171) <- peripheral starts up
[INFO ] dfu_split: firmware hash mismatch (peripheral=0x6938687c, expected=0x67363949), starting update (31264 bytes) (rmk src/split/driver.rs:181) <- firmware hashes don't match, update peripheral with embedded firmware in central
[INFO ] dfu_split: sending chunk at offset 0 (256 bytes) (rmk src/split/driver.rs:276)
[INFO ] dfu_split: sending chunk at offset 256 (256 bytes) (rmk src/split/driver.rs:276)
[INFO ] dfu_split: sending chunk at offset 512 (256 bytes) (rmk src/split/driver.rs:276)
... chunks keep coming
[INFO ] dfu_split: sending chunk at offset 30976 (256 bytes) (rmk src/split/driver.rs:276)
[INFO ] dfu_split: sending chunk at offset 31232 (32 bytes) (rmk src/split/driver.rs:276)
[INFO ] dfu_split: all chunks sent, signaling update complete (rmk src/split/driver.rs:312)
[INFO ] dfu_split: peripheral confirmed, update complete (rmk src/split/driver.rs:323)
[WARN ] Framing error (embassy_rp src/uart/buffered.rs:538) <- peripheral restart
[WARN ] Break error (embassy_rp src/uart/buffered.rs:544)
[ERROR] Peripheral message read error: SerialError (rmk src/split/driver.rs:146)
[INFO ] dfu_split: proactive hash from peripheral (0x67363949), checking... (rmk src/split/driver.rs:171) <- peripheral starts up, sends its firmwares CRC
[INFO ] dfu_split: peripheral firmware hash matches (0x67363949), no update needed (rmk src/split/driver.rs:176) <- firmware flashed successfully, no update needed

The AI overlords drew this for me, all hail to the AI overlords:

┌─────────────────────────────────────────────────────────────────────┐
│                      SPLIT DFU UPDATE                               │
│   (peripheral connects / is connected)                              │
└─────────────────────────────────────────────────────────────────────┘


═══ PHASE 0: HANDSHAKE ── hash comparison ───────────────────────────
Do we need to update the peripheral? 

  Central                           Peripheral
    │                                   │
    │                                   ├── (on boot) FirmwareHashResponse(hash)
    │                                   │   <- read_embedded_firmware_hash()
    │                                   │   = CRC32(__vector_table..__veneer_limit)
    │                                   │
    │  ── or ──                         │
    │                                   │
    ├── FirmwareHashQuery ─────────────>│
    │<── FirmwareHashResponse(hash) ────┤
    │                                   │
    │  hash == expected_hash?           │
    │    ├─ Yes → STOP (up-to-date)     │
    │    └─ No  → ⬇                     │
    │                                   │


═══ PHASE 1: CHUNK TRANSFER ── per-chunk CRC ────────────────────────
During transfer central calculates CRC of every chunk it sends, peripheral does as well and 
sends the CRC back in a FirmwareChunkAck. If they match, central sends the next chunk. 
If they don't match, retry the chunk. 
During sending Central calculates the overall CRC over all chunks sent. (central_crc.update(chunk))

  (outer attempt loop: 1..3)

  Central                           Peripheral
    │                                   │
    │ LED ON                            │
    │ central_crc = Crc32::new()        │
    │                                   │
    │   for chunk in firmware[256]:     │
    │     chunk_crc = CRC32(chunk)      │
    │     central_crc.update(chunk)     │
    │                                   │
    │   retry = 0                       │
    │   ┌─ retry < 3 ─────────────────┐ │
    │   │                             │ │
    ├── FirmwareChunk{offset,data} ──>│ │
    │   │                             │ │
    │   │               handler.write_chunk() — full erase on 1st call
    │   │               chunk_crc = CRC32(chunk) │
    │   │                             │ │
    │   │<─ FirmwareChunkAck{offset,──┤ │
    │   │         crc: chunk_crc}     │ │
    │   │                             │ │
    │   CRC match:                    │ │
    │   ack_crc == chunk_crc?         │ │
    │     ├─ Yes → next chunk         │ │
    │     └─ No  → retry++ ────── ────┘ │
    │                                   │
    │   All chunks acked?               │
    │     ├─ Yes → ⬇                    │
    │     └─ No  → attempt++ → Phase 1  │


═══ PHASE 2: END-TO-END CRC ── flash readback ──────────────────────
After all chunks are done, central compares CRC from chunk updates with the firmare CRC from phase 0, and if ok, central sends FirmwareUpdateComplete to peripheral.
Peripheral calculates the CRC over the firmware in DFU partition, sends FirmwareCrcReport(dfu_crc)
to central. Central compares that dfu_crc to the firmware CRC from phase 0, if match sends  FirmwareCrcOk to peripheral, peripheral answers FirmwareUpdateConfirm, marks updated to embassy-boot (SWAP_MAGIC) and resets. 

  Central                           Peripheral
    │                                   │
    │ central_crc.finalize()            │
    │ == expected_hash?                 │
    │   ├─ No  → ABORT (binary bug!)    │
    │   └─ Yes → ⬇                      │
    │                                   │
    ├── FirmwareUpdateComplete ────────>│
    │                                   │
    │                     handler.compute_dfu_crc()
    │                     = CRC32(whole DFU partition)
    │                     via flash readback (256B blocks)
    │                                   │
    │<── FirmwareCrcReport(dfu_crc) ────┤
    │                                   │
    │  dfu_crc == expected_hash?        │
    │    ├─ Yes → ⬇                     │
    │    └─ No  → send CrcFail ─────┐   │
    │                               │   │
    │                               │   attempt++ → Phase 1
    │                               │   │
    │    ├── FirmwareCrcOk ────────>│   │
    │    │                          │   │
    │    │                handler.mark_updated_and_reset()
    │    │               (only after CrcOk — never into corrupt FW)
    │    │                          │   │
    │    │<─ FirmwareUpdateConfirm ─┤   │
    │    │                          │   │
    │    │  DONE ── LED OFF         │   │
    │    │                          │   │
    │    └── CrCok in 5s? ──────────│   │
    │         No → timeout → abort  │   │
    │                               │   │
    │    └── CrcFail in 5s? ───── ──┤   │
    │         No → timeout → abort ─┘   │


═══ RETRY SUMMARY ════════════════════════════════════════════════════

  Layer           Max     Trigger                    Consequence
  ─────           ───     ───────                    ──────────
  Per-chunk       3×      Ack CRC mismatch           Re-send same chunk
                          or 2s timeout

  Outer attempt   3×      Chunk never acked          Full restart of
                          or E2E CRC mismatch        Phase 1 + 2
                          or CRC timeout

  No retry        —       Central CRC != expected    Abort — binary
                          (central_crc.finalize())   mismatch, not TX


═══ SAFETY GATES ════════════════════════════════════════════════════

  Where               What                          Why
  ─────               ────                          ───
  Peripheral boot     mark_updated_and_reset()       Never boot into
                      only on FirmwareCrcOk          corrupt firmware

  After all chunks    central_crc == expected_hash   Catch binary bugs
                                                    before asking peripheral

  End-to-end          compute_dfu_crc()             Catch silent flash
                      flash readback                write errors

  Per-chunk           CRC32(data) in Ack            Catch bitflips,
                                                    packet loss,
                                                    wrong offset

@Schievel1 Schievel1 force-pushed the embassy-boot-flash-peripheral branch from 4fe7d4c to 5ce436b Compare June 20, 2026 21:22
@Schievel1 Schievel1 changed the title feat(dfu_split): Embassy boot flash peripheral from central (RP2040 only) feat(dfu_split): Embassy boot flash peripheral from central Jun 20, 2026
@Schievel1 Schievel1 force-pushed the embassy-boot-flash-peripheral branch from 82f55ac to f8cac52 Compare June 22, 2026 19:49
@Schievel1 Schievel1 force-pushed the embassy-boot-flash-peripheral branch 16 times, most recently from 396b095 to 6a9363b Compare July 4, 2026 23:14
@github-actions

github-actions Bot commented Jul 4, 2026

Copy link
Copy Markdown

Size Report

Example main PR Diff .text .data .bss
use_config/nrf52832_ble 394.8 KiB 394.8 KiB +0.00% ⬇️ -4 0 0
use_config/nrf52840_ble 443.3 KiB 443.3 KiB +0.00% ⬇️ -12 0 0
use_config/nrf52840_ble_split (central) 492.5 KiB 492.5 KiB +0.00% ⬆️ +32 0 +16
use_config/nrf52840_ble_split (peripheral) 316.9 KiB 316.9 KiB +0.00% ⬆️ +8 0 0
use_config/pi_pico_w_ble 667.6 KiB 667.9 KiB +0.04% ⬆️ +304 0 0
use_config/rp2040 148.5 KiB 148.5 KiB +0.00% ⬆️ +8 0 0
use_config/rp2040_split (central) 162.1 KiB 162.2 KiB +0.05% ⬆️ +76 0 +16
use_config/rp2040_split (peripheral) 27.8 KiB 27.8 KiB +0.01% ⬆️ +4 0 0
use_config/stm32f1 63.0 KiB 63.0 KiB +0.00% 0 0 0
use_config/stm32h7 100.0 KiB 100.0 KiB +0.00% ⬇️ -4 0 0
use_rust/nrf52832_ble 382.2 KiB 382.2 KiB +0.00% ⬇️ -4 0 0
use_rust/nrf52840_ble 438.6 KiB 438.6 KiB +0.00% ⬆️ +4 0 0
use_rust/nrf52840_ble_split (central) 501.8 KiB 502.0 KiB +0.02% ⬆️ +104 0 +16
use_rust/nrf52840_ble_split (peripheral) 313.3 KiB 313.3 KiB +0.00% ⬆️ +12 0 0
use_rust/pi_pico_w_ble 668.2 KiB 668.2 KiB +0.00% ⬆️ +8 0 0
use_rust/rp2040 148.0 KiB 148.0 KiB +0.00% ⬆️ +4 0 0
use_rust/rp2040_split (central) 160.8 KiB 160.8 KiB +0.02% ⬆️ +20 0 +16
use_rust/rp2040_split (peripheral) 28.1 KiB 28.1 KiB +0.01% ⬆️ +4 0 0
use_rust/stm32f1 62.9 KiB 62.9 KiB +0.00% ⬇️ -4 0 0
use_rust/stm32h7 122.3 KiB 122.3 KiB +0.00% 0 0 0
use_config/nrf52832_ble — 394.8 KiB → 394.8 KiB (+0.00% ⬇️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 364956	   4588	  34760	 404304	  62b50	rmk-nrf52832

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 364960	   4588	  34760	 404308	  62b54	rmk-nrf52832

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%    +329  [ = ]       0    .debug_str
  +0.0%     +13  [ = ]       0    .strtab
  +6.0%      +4  [ = ]       0    [Unmapped]
  -0.0%      -4  -0.0%      -4    .text
  -0.2%     -16  [ = ]       0    .debug_abbrev
  -0.0%    -127  [ = ]       0    .debug_line
  -0.0%    -719  [ = ]       0    .debug_info
  -0.0%    -520  -0.0%      -4    TOTAL
use_config/nrf52840_ble — 443.3 KiB → 443.3 KiB (+0.00% ⬇️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 397912	   4596	  51416	 453924	  6ed24	rmk-nrf52840

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 397924	   4596	  51416	 453936	  6ed30	rmk-nrf52840

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%     +68  [ = ]       0    .debug_info
  +0.0%     +12  [ = ]       0    .strtab
   +20%     +11  [ = ]       0    [Unmapped]
  -0.0%     -10  [ = ]       0    .debug_loc
  -0.0%     -12  -0.0%     -12    .text
  -0.0%     -16  [ = ]       0    .debug_line
  -0.0%    -793  [ = ]       0    .debug_str
  -0.0%    -740  -0.0%     -12    TOTAL
use_config/nrf52840_ble_split (central) — 492.5 KiB → 492.5 KiB (+0.00% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 452868	   4652	  46824	 504344	  7b218	central

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 452836	   4652	  46808	 504296	  7b1e8	central

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1% +2.68Ki  [ = ]       0    .debug_str
  +0.1%    +160  [ = ]       0    .symtab
  +0.0%     +88  [ = ]       0    .strtab
  +0.1%     +64  [ = ]       0    .debug_frame
  +0.1%     +32  [ = ]       0    .debug_aranges
  +0.0%     +32  +0.0%     +32    .text
  [ = ]       0  +0.0%     +16    .bss
  -0.0%     -80  [ = ]       0    .debug_info
  -0.0%     -83  [ = ]       0    .debug_line
  -0.1%    -160  [ = ]       0    .debug_ranges
  -0.0%    -352  [ = ]       0    .debug_loc
  +0.0% +2.39Ki  +0.0%     +48    TOTAL
use_config/nrf52840_ble_split (peripheral) — 316.9 KiB → 316.9 KiB (+0.00% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 292936	   4468	  27152	 324556	  4f3cc	peripheral

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 292928	   4468	  27152	 324548	  4f3c4	peripheral

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%     +10  [ = ]       0    .debug_line
  +0.0%      +8  +0.0%      +8    .text
  -5.0%      -3  [ = ]       0    [Unmapped]
  -0.0%      -7  [ = ]       0    .strtab
  -0.0%     -10  [ = ]       0    .debug_loc
  -0.0%    -101  [ = ]       0    .debug_info
  -0.0% -1.24Ki  [ = ]       0    .debug_str
  -0.0% -1.34Ki  +0.0%      +8    TOTAL
use_config/pi_pico_w_ble — 667.6 KiB → 667.9 KiB (+0.04% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 629340	      0	  54604	 683944	  a6fa8	rmk-pi-pico-w

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 629036	      0	  54604	 683640	  a6e78	rmk-pi-pico-w

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1% +1.50Ki  [ = ]       0    .debug_loc
  +0.0% +1.12Ki  [ = ]       0    .debug_info
  +0.0% +1.07Ki  [ = ]       0    .debug_str
  +0.2%    +532  [ = ]       0    .strtab
  +0.2%    +424  [ = ]       0    .debug_ranges
  +0.1%    +400  [ = ]       0    .debug_line
  +0.1%    +304  +0.1%    +304    .text
  +0.1%     +80  [ = ]       0    .symtab
  +0.2%     +68  [ = ]       0    .debug_frame
  +0.0%     +16  [ = ]       0    .debug_aranges
 -22.9%     -16  [ = ]       0    [Unmapped]
  +0.1% +5.45Ki  +0.0%    +304    TOTAL
use_config/rp2040 — 148.5 KiB → 148.5 KiB (+0.00% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 136528	      0	  15540	 152068	  25204	rmk-rp2040

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 136520	      0	  15540	 152060	  251fc	rmk-rp2040

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%    +240  [ = ]       0    .debug_str
  +0.0%    +165  [ = ]       0    .debug_info
  +0.1%    +124  [ = ]       0    .debug_line
   +59%     +24  [ = ]       0    [Unmapped]
  +0.0%     +15  [ = ]       0    .strtab
  +0.0%      +8  +0.0%      +8    .text
  +0.0%    +576  +0.0%      +8    TOTAL
use_config/rp2040_split (central) — 162.1 KiB → 162.2 KiB (+0.05% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 149648	      0	  16404	 166052	  288a4	central

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 149572	      0	  16388	 165960	  28848	central

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1% +1.41Ki  [ = ]       0    .debug_str
  +0.2%    +911  [ = ]       0    .debug_loc
  +0.0%    +285  [ = ]       0    .debug_info
  +0.3%     +96  [ = ]       0    .symtab
  +0.1%     +76  +0.1%     +76    .text
   +50%     +22  [ = ]       0    [Unmapped]
  [ = ]       0  +0.1%     +16    .bss
  +0.0%      +1  [ = ]       0    .strtab
  -0.0%     -32  [ = ]       0    .debug_line
  +0.1% +2.74Ki  +0.1%     +92    TOTAL
use_config/rp2040_split (peripheral) — 27.8 KiB → 27.8 KiB (+0.01% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
  25596	     60	   2796	  28452	   6f24	peripheral

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
  25592	     60	   2796	  28448	   6f20	peripheral

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%      +5  [ = ]       0    .debug_line
  +0.1%      +4  +0.1%      +4    .rodata
  -0.0%      -2  [ = ]       0    .strtab
  -4.9%      -3  [ = ]       0    [Unmapped]
  -0.0%     -16  [ = ]       0    .debug_str
  -0.0%     -12  +0.0%      +4    TOTAL
use_config/stm32f1 — 63.0 KiB → 63.0 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
  56956	     28	   7520	  64504	   fbf8	rmk-stm32f1

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
  56956	     28	   7520	  64504	   fbf8	rmk-stm32f1

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%      +4  [ = ]       0    .debug_line
  +1.9%      +1  [ = ]       0    [Unmapped]
  -0.0%    -234  [ = ]       0    .debug_info
  -0.2% -1.11Ki  [ = ]       0    .debug_str
  -0.1% -1.34Ki  [ = ]       0    TOTAL
use_config/stm32h7 — 100.0 KiB → 100.0 KiB (+0.00% ⬇️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
  92396	    268	   9760	 102424	  19018	rmk-stm32h7

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
  92400	    268	   9760	 102428	  1901c	rmk-stm32h7

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1%    +153  [ = ]       0    .debug_line
  +0.0%     +24  [ = ]       0    .debug_str
   +15%      +8  [ = ]       0    [Unmapped]
  +0.0%      +7  [ = ]       0    .debug_info
  -0.0%      -4  -0.0%      -4    .text
  +0.0%    +188  -0.0%      -4    TOTAL
use_rust/nrf52832_ble — 382.2 KiB → 382.2 KiB (+0.00% ⬇️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 353016	   4588	  33744	 391348	  5f8b4	rmk-nrf52832

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 353020	   4588	  33744	 391352	  5f8b8	rmk-nrf52832

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1% +1.47Ki  [ = ]       0    .debug_str
  +0.0%     +28  [ = ]       0    .debug_line
   +16%      +6  [ = ]       0    [Unmapped]
  -0.0%      -2  [ = ]       0    .strtab
  -0.0%      -4  -0.0%      -4    .text
  -0.0%     -10  [ = ]       0    .debug_loc
  -0.0%    -416  [ = ]       0    .debug_info
  +0.0% +1.08Ki  -0.0%      -4    TOTAL
use_rust/nrf52840_ble — 438.6 KiB → 438.6 KiB (+0.00% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 397588	   4596	  46904	 449088	  6da40	rmk-nrf52840

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 397584	   4596	  46904	 449084	  6da3c	rmk-nrf52840

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%    +882  [ = ]       0    .debug_str
  +0.0%    +672  [ = ]       0    .debug_info
   +62%     +28  [ = ]       0    [Unmapped]
  +0.0%     +21  [ = ]       0    .debug_line
  +0.0%     +10  [ = ]       0    .debug_loc
  +0.0%      +4  +0.0%      +4    .text
  +0.0%      +2  [ = ]       0    .strtab
  -0.6%     -55  [ = ]       0    .debug_abbrev
  +0.0% +1.53Ki  +0.0%      +4    TOTAL
use_rust/nrf52840_ble_split (central) — 501.8 KiB → 502.0 KiB (+0.02% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 456792	   4652	  52568	 514012	  7d7dc	central

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 456688	   4652	  52552	 513892	  7d764	central

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1% +4.10Ki  [ = ]       0    .debug_str
  +0.1% +1.20Ki  [ = ]       0    .debug_info
  +0.1%    +199  [ = ]       0    .debug_line
  +0.0%    +104  +0.0%    +104    .text
  +0.0%     +64  [ = ]       0    .symtab
  +0.0%     +40  [ = ]       0    .debug_ranges
  [ = ]       0  +0.0%     +16    .bss
  +0.0%     +16  [ = ]       0    .debug_frame
  +0.0%     +14  [ = ]       0    .strtab
  +0.0%      +8  [ = ]       0    .debug_aranges
 -10.2%      -5  [ = ]       0    [Unmapped]
  -0.1%    -444  [ = ]       0    .debug_loc
  +0.1% +5.29Ki  +0.0%    +120    TOTAL
use_rust/nrf52840_ble_split (peripheral) — 313.3 KiB → 313.3 KiB (+0.00% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 290920	   4468	  25400	 320788	  4e514	peripheral

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 290908	   4468	  25400	 320776	  4e508	peripheral

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%    +178  [ = ]       0    .debug_info
  +0.0%     +12  +0.0%     +12    .text
  +0.0%     +11  [ = ]       0    .debug_line
  -0.0%      -7  [ = ]       0    .strtab
  -0.0%     -10  [ = ]       0    .debug_loc
 -15.4%     -10  [ = ]       0    [Unmapped]
  -0.0%    -246  [ = ]       0    .debug_str
  -0.0%     -72  +0.0%     +12    TOTAL
use_rust/pi_pico_w_ble — 668.2 KiB → 668.2 KiB (+0.00% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 629504	      0	  54748	 684252	  a70dc	rmk-pi-pico-w

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 629496	      0	  54748	 684244	  a70d4	rmk-pi-pico-w

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%    +927  [ = ]       0    .debug_str
  +0.0%    +427  [ = ]       0    .debug_info
  +0.0%     +42  [ = ]       0    .debug_loc
  +0.0%     +23  [ = ]       0    .strtab
  +0.0%     +22  [ = ]       0    .debug_line
  +0.0%      +8  +0.0%      +8    .text
  -8.9%      -5  [ = ]       0    [Unmapped]
  +0.0% +1.41Ki  +0.0%      +8    TOTAL
use_rust/rp2040 — 148.0 KiB → 148.0 KiB (+0.00% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 136184	      0	  15412	 151596	  2502c	rmk-rp2040

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 136180	      0	  15412	 151592	  25028	rmk-rp2040

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1%     +98  [ = ]       0    .debug_line
  +0.0%     +15  [ = ]       0    .strtab
  +0.0%      +4  +0.0%      +4    .text
  -3.3%      -2  [ = ]       0    [Unmapped]
  -0.0%    -121  [ = ]       0    .debug_info
  -0.0%    -186  [ = ]       0    .debug_str
  -0.0%    -192  +0.0%      +4    TOTAL
use_rust/rp2040_split (central) — 160.8 KiB → 160.8 KiB (+0.02% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 148476	      0	  16188	 164664	  28338	central

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 148456	      0	  16172	 164628	  28314	central

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.6% +1.94Ki  [ = ]       0    .debug_loc
  +0.1% +1.08Ki  [ = ]       0    .debug_str
  +0.1%     +64  [ = ]       0    .debug_ranges
  +0.0%     +20  +0.0%     +20    .text
  [ = ]       0  +0.1%     +16    .bss
   +28%     +11  [ = ]       0    [Unmapped]
  -0.0%     -17  [ = ]       0    .strtab
  -0.0%     -52  [ = ]       0    .debug_line
  -0.0%    -115  [ = ]       0    .debug_info
  +0.1% +2.93Ki  +0.0%     +36    TOTAL
use_rust/rp2040_split (peripheral) — 28.1 KiB → 28.1 KiB (+0.01% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
  25656	     60	   3060	  28776	   7068	peripheral

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
  25652	     60	   3060	  28772	   7064	peripheral

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%      +7  [ = ]       0    .debug_line
  +0.1%      +4  +0.1%      +4    .rodata
  -0.0%      -2  [ = ]       0    .strtab
  -3.2%      -2  [ = ]       0    [Unmapped]
  -0.0%     -15  [ = ]       0    .debug_str
  -0.0%      -8  +0.0%      +4    TOTAL
use_rust/stm32f1 — 62.9 KiB → 62.9 KiB (+0.00% ⬇️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
  56892	     28	   7496	  64416	   fba0	rmk-stm32f1

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
  56896	     28	   7496	  64420	   fba4	rmk-stm32f1

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
   +17%      +9  [ = ]       0    [Unmapped]
  -0.0%      -4  -0.0%      -4    .text
  -0.0%     -34  [ = ]       0    .debug_line
  -0.1%    -536  [ = ]       0    .debug_info
  -0.1%    -767  [ = ]       0    .debug_str
  -0.1% -1.30Ki  -0.0%      -4    TOTAL
use_rust/stm32h7 — 122.3 KiB → 122.3 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 109188	    324	  15692	 125204	  1e914	rmk-stm32h7

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 109188	    324	  15692	 125204	  1e914	rmk-stm32h7

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  -4.9%      -2  [ = ]       0    [Unmapped]
  -0.0%      -4  [ = ]       0    .strtab
  -0.1%    -147  [ = ]       0    .debug_line
  -0.0%    -270  [ = ]       0    .debug_info
  -0.0%    -429  [ = ]       0    .debug_str
  -0.0%    -852  [ = ]       0    TOTAL

… central

Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
@Schievel1 Schievel1 force-pushed the embassy-boot-flash-peripheral branch from 6a9363b to f667f20 Compare July 4, 2026 23:24
@Schievel1 Schievel1 marked this pull request as ready for review July 4, 2026 23:24
@HaoboGu

HaoboGu commented Jul 8, 2026

Copy link
Copy Markdown
Owner

I think it's worth to support external nor flash as the storage used by dfu split. The remaining flash space is quite tight even for nRF52840(which has 1M flash)

@Schievel1

Schievel1 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

I think it's worth to support external nor flash as the storage used by dfu split. The remaining flash space is quite tight even for nRF52840(which has 1M flash)

For the embedded peripheral firmware in central or the flashing peripheral via central relay?
For the latter we can not do that, because the bootloader would need access to the external flash. This creates tons of problems with different chips with different flash types so you would have a bouquet of bootloaders supporting different boards.
For the first, iirc nrf52840 isn't supported for this anyway right now, since dfu_split only supports uart split and RMK does not support nrf uart splits. This works for RP2040 only at the moment, and RP2040 has 2M or more, which is plenty for firmware that isn't bloated by the BLE stack.

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