Skip to content

feat(dfu_ext): Add ext dfu flash - #1030

Draft
Schievel1 wants to merge 1 commit into
rmk-rs:mainfrom
Schievel1:add-ext-DFU-flash
Draft

feat(dfu_ext): Add ext dfu flash#1030
Schievel1 wants to merge 1 commit into
rmk-rs:mainfrom
Schievel1:add-ext-DFU-flash

Conversation

@Schievel1

@Schievel1 Schievel1 commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Add possibility to use external flash as DFU partition.
Also a partial rewrite of DFU architecture. I split the struct dfustate into two separate structs. The first struct, UsbProxyDfuHandler only forwards DFU commands into a channel. This struct is the USB handler and has static lifetime. The second struct, RmkDfuInterface holds the partitions and doesn't need static lifetime. It blocks on messages from that channel and does the writing into partitions, mark updated and such. The result is that partitions do not need to be in static cells.
Only downside it that someone has to run that handler with the partitions now but I think that's fair enough.

Tests I need to carry out on hardware:

Done Platform Test Bootloader build (cargo features)
[ ] nRF52833 DFU flash & swap nrf52833
[ ] nRF52833 DFU flash & rollback nrf52833
[ ] nRF52833 Bootloader direct DFU flash & swap nrf52833
[ ] nRF52833 Bootloader direct DFU flash & rollback nrf52833
[ ] nRF52833 noswap bootloader direct DFU flash nrf52833,noswap
[ ] nRF52833 dfu_ext flash & swap nrf52833,dfu_ext
[ ] nRF52833 dfu_ext flash & rollback nrf52833,dfu_ext
[ ] nRF52833 dfu_ext bootloader direct DFU flash & swap nrf52833,dfu_ext
[ ] nRF52833 dfu_ext bootloader direct DFU flash & rollback nrf52833,dfu_ext
[x] nRF52840 DFU flash & swap nrf52840
[x] nRF52840 DFU flash & rollback nrf52840
[x] nRF52840 Bootloader direct DFU flash & swap nrf52840
[x] nRF52840 Bootloader direct DFU flash & rollback nrf52840
[x] nRF52840 noswap bootloader direct DFU flash nrf52840,noswap
[x] nRF52840 dfu_ext flash & swap nrf52840,dfu_ext
[x] nRF52840 dfu_ext flash & rollback nrf52840,dfu_ext
[x] nRF52840 dfu_ext bootloader direct DFU flash & swap nrf52840,dfu_ext
[x] nRF52840 dfu_ext bootloader direct DFU flash & rollback nrf52840,dfu_ext
[x] RP2040-2MB DFU flash & swap rp2040,rp2040-2mb
[x] RP2040-2MB DFU flash & rollback rp2040,rp2040-2mb
[x] RP2040-2MB dfu_split flash & swap rp2040,rp2040-2mb
[x] RP2040-2MB dfu_split flash & rollback rp2040,rp2040-2mb
[x] RP2040-2MB dfu_split, dfu_ext flash & swap rp2040,rp2040-2mb,dfu_ext
[x] RP2040-2MB dfu_split, dfu_ext flash & rollback rp2040,rp2040-2mb,dfu_ext
[x] RP2040-2MB dfu_ext flash & swap rp2040,rp2040-2mb,dfu_ext
[x] RP2040-2MB dfu_ext flash & rollback rp2040,rp2040-2mb,dfu_ext

Comment thread rmk/src/dfu/mod.rs Outdated
/// Requires `rmk-boot.x` to be linked into the firmware binary
/// (e.g. `-Trmk-boot.x` in `.cargo/config.toml`).
#[cfg(any(feature = "dfu_rp", feature = "dfu_nrf"))]
pub fn init_flash_from_linkerscript(flash: FlashType) -> PartitionType {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

honestly, best I can do is hiding the type behind a FlashType and importing the concrete type depending on feature set.

The problem is, that the flash must be stored in a static for the usb registration, but static can't be generics.
So in order to have this as impl NorFlash the user would have to make this static, which overcomplicates the user facing API imo.

Maybe you have a better idea.

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.

The current design can be simplified a lot by using NorFlash, and 'static is not needed actually.

We can just have:

pub struct RmkDfuInterface<'d, DFU: NorFlash, STATE: NorFlash> {
    central: DfuState<RmkDfuHandler<FirmwareHandler<'d, DFU, STATE, ResetImmediate, BLOCK_SIZE_DFU>>>,
    #[cfg(feature = "dfu_split")]
    passthrough: [Option<DfuState<RmkDfuHandler<PassthroughDfuHandler>>>; MAX_PASSTHROUGH_ALTS],
    #[cfg(feature = "dfu_split")]
    num_passthrough: usize,
    current_alt: u8,
}
impl<'d, DFU: NorFlash, STATE: NorFlash> RmkDfuInterface<'d, DFU, STATE> {
    pub fn new(
        dfu: DFU,
        state: STATE,
        aligned: &'d mut AlignedBuffer<DFU_ALIGN>,
        #[cfg(feature = "dfu_split")] num_peripherals: usize,
    ) -> Self {
        const { assert!(STATE::WRITE_SIZE <= DFU_ALIGN) };
        let updater = BlockingFirmwareUpdater::new(
            FirmwareUpdaterConfig { dfu, state },
            &mut aligned.0[..STATE::WRITE_SIZE],
        );
        // ...
    }
}

pub fn mark_booted(state: impl NorFlash, aligned: &mut AlignedBuffer<DFU_ALIGN>);

And in the user code it becomes:

let flash = Mutex::<CriticalSectionRawMutex, _>::new(RefCell::new(Nvmc::new(p.NVMC)));
let mut aligned = AlignedBuffer([0; 32]);

rmk::dfu::mark_booted(BlockingPartition::new(&flash, STATE_OFFSET, STATE_SIZE), &mut aligned);

let mut dfu = RmkDfuInterface::new(
    BlockingPartition::new(&flash, DFU_OFFSET, DFU_SIZE),
    BlockingPartition::new(&flash, STATE_OFFSET, STATE_SIZE),
    &mut aligned,
    SPLIT_PERIPHERALS_NUM,
);

let storage = async_flash_wrapper(BlockingPartition::new(&flash, STORAGE_OFFSET, STORAGE_SIZE));

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The UsbTransport requires things to have static lifetime.
src/usb/mod.rs:

pub struct UsbTransport<'a, D: Driver<'static>> {

and

impl<'a, D: Driver<'static>> UsbTransport<'a, D> {
    pub fn new(driver: D, device_config: DeviceConfig<'static>) -> Self {

Only way to do static I think is when the type is known, and it's only known in user code. So we have to shift what we do here into user code. (the let flash_mutex: &'static MutexType = FLASH_CELL.init(Mutex::new(RefCell::new(flash)));)

Like this:

// types only added to make things a bit easier to overlook
type InternalFlashMutex =
    Mutex<CriticalSectionRawMutex, RefCell<Flash<'static, FLASH, Blocking, { rmk::dfu::FLASH_SIZE }>>>;
type InternalFlashPartition =
    BlockingPartition<'static, CriticalSectionRawMutex, Flash<'static, FLASH, Blocking, { rmk::dfu::FLASH_SIZE }>>;


    static FLASH_MUTEX: StaticCell<InternalFlashMutex> = StaticCell::new();
    let flash_mutex = FLASH_MUTEX.init(InternalFlashMutex::new(RefCell::new(embassy_rp::flash::Flash::<
        _,
        embassy_rp::flash::Blocking,
        { rmk::dfu::FLASH_SIZE },
    >::new_blocking(p.FLASH))));

    let state_partition =
        InternalFlashPartition::new(flash_mutex, dfu_flash_layout.state_offset, dfu_flash_layout.state_size);
    let flash = async_flash_wrapper(InternalFlashPartition::new(
        flash_mutex,
        dfu_flash_layout.storage_offset,
        dfu_flash_layout.storage_size,
    ));


I will try to make UsbTransport & co a shorter lifetime, but that is a bigger change.

@Schievel1 Schievel1 Aug 12, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I will try to make UsbTransport & co a shorter lifetime, but that is a bigger change.

I tinkered around with this, but I think it only gets worse from here.
So I think we should be going what you proposed, instead of hiding the staticcell complexity behind a function that needs concrete types and therefore must be implemented separately for each.

type ExternalFlash = W25qNorFlash<spi::Spi<'static, peripherals::SPI0, spi::Blocking>, Output<'static>>;
type ExternalPartition = BlockingPartition<'static, CriticalSectionRawMutex, ExternalFlash>;
type InternalFlashMutex =
    Mutex<CriticalSectionRawMutex, RefCell<Flash<'static, FLASH, Blocking, { rmk::dfu::FLASH_SIZE }>>>;
type InternalFlashPartition =
    BlockingPartition<'static, CriticalSectionRawMutex, Flash<'static, FLASH, Blocking, { rmk::dfu::FLASH_SIZE }>>;


#[embassy_executor::main]
async fn main(_spawner: Spawner) {
    static DFU_MUTEX: StaticCell<Mutex<CriticalSectionRawMutex, RefCell<ExternalFlash>>> = StaticCell::new();
    let dfu_mutex = DFU_MUTEX.init(Mutex::new(RefCell::new(ext_flash)));
    let dfu_partition = ExternalPartition::new(dfu_mutex, 0, dfu_mutex.lock(|c| c.borrow().capacity() as u32));

    let dfu_flash_layout = dfu_flash_layout();
    static FLASH_MUTEX: StaticCell<InternalFlashMutex> = StaticCell::new();
    let flash_mutex = FLASH_MUTEX.init(InternalFlashMutex::new(RefCell::new(embassy_rp::flash::Flash::<
        _,
        embassy_rp::flash::Blocking,
        { rmk::dfu::FLASH_SIZE },
    >::new_blocking(p.FLASH))));
    let mut state_partition =
        InternalFlashPartition::new(flash_mutex, dfu_flash_layout.state_offset, dfu_flash_layout.state_size);
    let flash = async_flash_wrapper(InternalFlashPartition::new(
        flash_mutex,
        dfu_flash_layout.storage_offset,
        dfu_flash_layout.storage_size,
    ));


    rmk::dfu::mark_booted(&mut state_partition);


    static DFU_IFACE: StaticCell<rmk::dfu::RmkDfuInterface<ExternalPartition, InternalFlashPartition>> =
        StaticCell::new();
    let dfu_iface = DFU_IFACE.init(rmk::dfu::RmkDfuInterface::new(dfu_partition, state_partition));
    let mut usb_transport =
        UsbTransport::new_with_dfu(driver, rmk_config.device_config, dfu_iface).with_host_service(&host_service);

// ...
}

The handler is then generic over norflash:

pub struct RmkDfuInterface<'d, DFU: NorFlash, STATE: NorFlash> {
    central: DfuState<RmkDfuHandler<FirmwareHandler<'d, DFU, STATE, ResetImmediate, BLOCK_SIZE_DFU>>>,
    #[cfg(feature = "dfu_split")]
    passthrough: [Option<DfuState<RmkDfuHandler<PassthroughDfuHandler>>>; MAX_PASSTHROUGH_ALTS],
    #[cfg(feature = "dfu_split")]
    num_passthrough: usize,
    current_alt: u8,
}

impl<'d, DFU: NorFlash, STATE: NorFlash> RmkDfuInterface<'d, DFU, STATE> {
    /// Build the DFU interface from a DFU download partition and a boot state
    /// partition.
    pub fn new(dfu: DFU, state: STATE, #[cfg(feature = "dfu_split")] num_peripherals: usize) -> Self {
...

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.

What I don't understand is, why UsbTransport needs dfu_iface? The transport should do the transport thing only, forward the data to the DFU part. So it should not own dfu info.

@Schievel1 Schievel1 Aug 12, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Is all comes down to embassy-usb-dfu and embassy-boot do not split partition ownership and usb handling apart.

Ultimately the partitions are owned by the BlockingFirmwareUpdater in embassy-boot.
The BlockingFirmwareUpdater is owned by the FirmwareHandler in embassy-usb-dfu, which in turn is owned (& wrapped) by RmkDfuHandler which is owned by DfuState which does the usb stuff.

Maybe I can split the usb part and the firmware handler apart. DfuState gets a handler that only does forward messages between the usb and the actual firmware handler. The actual one then could live on the stack in main and hold the partitions and do the DFU stuff with them if it's receiving messages.

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.

The solution is to create separated Partitions for DFU & Storage? The Partition already implements NorFlash if I remember it correctly

For example:

pub type DfuFlash<F> = embassy_sync::mutex::Mutex<CriticalSectionRawMutex, F>;
pub type DfuPartition<'a, F> = embassy_embedded_hal::flash::partition::Partition<'a, CriticalSectionRawMutex, F>;

pub fn partitions_from_linkerscript<F: NorFlash>(flash: &DfuFlash<F>) -> (DfuPartition<'_, F>, DfuSession<'_, F>) {
    use embassy_embedded_hal::flash::partition::Partition;

    unsafe extern "C" {
        static __bootloader_state_start: u8;
        static __bootloader_state_end: u8;
        static __bootloader_dfu_start: u8;
        static __bootloader_dfu_end: u8;
        static __bootloader_storage_start: u8;
        static __bootloader_storage_end: u8;
    }
    let part = |start: &u8, end: &u8| {
        let addr = |s: &u8| core::ptr::from_ref(s) as usize as u32;
        let (start, end) = (addr(start), addr(end));
        Partition::new(flash, start, end - start)
    };
    // SAFETY: linker-defined absolute symbols — reading their addresses is safe.
    unsafe {
        (
            part(&__bootloader_storage_start, &__bootloader_storage_end),
            DfuSession::new(
                part(&__bootloader_dfu_start, &__bootloader_dfu_end),
                part(&__bootloader_state_start, &__bootloader_state_end),
            ),
        )
    }
}

// user code
let dfu_flash = rmk::dfu::DfuFlash::new(rmk::storage::async_flash_wrapper(Nvmc::new(p.NVMC)));
let (flash, mut dfu_session) = rmk::dfu::partitions_from_linkerscript(&dfu_flash);

@Schievel1 Schievel1 Aug 19, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

DFU and Storage partitions have always been separate.
The solution is to separate USB handling for DFU and writing to the partitions.

Before: one handler does everything, usb requires that handler to be static, therefore everything that handler holds must be static. The handler holds the partition, so they had to be static.

Now: one handler does the USB handling for DFU, but all it does is piping the DFU commands into a channel. Another handler reads from the channel and does the flash operations for DFU and therefore holds the partitions.
Via the channel in the middle the lifetimes of both structs and therefore of the usb handler and the partitions are separated.

Have a look at one of the examples, they are pretty close now to what you proposed in the first place.
I think having a function that creates all the partitions directly from the linkerscript is also possible. Apart from the DFU partition in external flash, because that needs its own flash mutex.

Comment thread rmk/src/dfu/mod.rs Outdated
@Schievel1

Copy link
Copy Markdown
Contributor Author

Alright taking inspiration from the peripheraldfuhandler and its passthroughhandler I split the dfustate into two separate structs. The first only forwards dfu commands into a channel it is the usb handler and has static lifetime, the other holds the partitions and doesn't need static lifetime. It blocks on messages from that channel and does the writing into partitions, mark updated and such.

Only downside it that some has to run that handler with the partitions now but I think that's fair enough.

@Schievel1
Schievel1 force-pushed the add-ext-DFU-flash branch 11 times, most recently from b02818d to 40de1a5 Compare August 22, 2026 09:51
@github-actions

github-actions Bot commented Aug 22, 2026

Copy link
Copy Markdown

Size Report

Example main PR Diff .text .data .bss
use_config/nrf52832_ble 391.2 KiB 391.2 KiB +0.00% ⬆️ +4 0 0
use_config/nrf52840_ble 434.5 KiB 434.5 KiB +0.00% ⬆️ +4 0 0
use_config/nrf52840_ble_split (central) 495.3 KiB 495.3 KiB +0.00% 0 0 0
use_config/nrf52840_ble_split (peripheral) 316.6 KiB 316.6 KiB +0.00% 0 0 0
use_config/pi_pico_w_ble 677.3 KiB 677.3 KiB +0.00% ⬇️ -4 0 0
use_config/rp2040 146.1 KiB 146.1 KiB +0.00% 0 0 0
use_config/rp2040_split (central) 161.0 KiB 161.0 KiB +0.00% ⬇️ -4 0 0
use_config/rp2040_split (peripheral) 27.9 KiB 27.9 KiB +0.00% 0 0 0
use_config/stm32f1 62.4 KiB 62.4 KiB +0.00% 0 0 0
use_config/stm32h7 100.6 KiB 100.6 KiB +0.00% 0 0 0
use_rust/nrf52832_ble 379.6 KiB 379.6 KiB +0.00% ⬇️ -4 0 0
use_rust/nrf52840_ble 428.9 KiB 428.9 KiB +0.00% 0 0 0
use_rust/nrf52840_ble_split (central) 493.7 KiB 493.7 KiB +0.00% 0 0 0
use_rust/nrf52840_ble_split (peripheral) 308.6 KiB 308.6 KiB +0.00% 0 0 0
use_rust/pi_pico_w_ble 676.7 KiB 676.7 KiB +0.00% ⬆️ +8 0 0
use_rust/rp2040 145.7 KiB 145.7 KiB +0.00% 0 0 0
use_rust/rp2040_split (central) 159.6 KiB 159.6 KiB +0.00% ⬇️ -8 0 0
use_rust/rp2040_split (peripheral) 28.3 KiB 28.3 KiB +0.00% 0 0 0
use_rust/stm32f1 61.7 KiB 61.7 KiB +0.00% 0 0 0
use_rust/stm32h7 119.1 KiB 119.1 KiB +0.00% 0 0 0
use_config/nrf52832_ble — 391.2 KiB → 391.2 KiB (+0.00% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 358012	   8620	  33992	 400624	  61cf0	rmk-nrf52832

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 358008	   8620	  33992	 400620	  61cec	rmk-nrf52832

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%      +9  [ = ]       0    .debug_line
  +0.0%      +4  +0.0%      +4    .text
 -13.0%      -6  [ = ]       0    [Unmapped]
  -0.0%     -62  [ = ]       0    .debug_info
  -0.1%    -375  [ = ]       0    .strtab
  -0.1% -2.21Ki  [ = ]       0    .debug_str
  -0.0% -2.62Ki  +0.0%      +4    TOTAL
use_config/nrf52840_ble — 434.5 KiB → 434.5 KiB (+0.00% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 392296	   8628	  44024	 444948	  6ca14	rmk-nrf52840

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 392292	   8628	  44024	 444944	  6ca10	rmk-nrf52840

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%    +250  [ = ]       0    .debug_str
  +0.0%      +4  +0.0%      +4    .text
  +0.0%      +2  [ = ]       0    .strtab
 -10.9%      -7  [ = ]       0    [Unmapped]
  -0.0%     -14  [ = ]       0    .debug_loc
  -0.4%     -39  [ = ]       0    .debug_abbrev
  -0.0%     -40  [ = ]       0    .debug_info
  +0.0%    +156  +0.0%      +4    TOTAL
use_config/nrf52840_ble_split (central) — 495.3 KiB → 495.3 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 448400	   8668	  50120	 507188	  7bd34	central

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 448400	   8668	  50120	 507188	  7bd34	central

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%    +267  [ = ]       0    .debug_str
  +0.0%     +10  [ = ]       0    .debug_loc
  -6.6%      -5  [ = ]       0    [Unmapped]
  -0.0%     -17  [ = ]       0    .strtab
  -0.0%    -135  [ = ]       0    .debug_info
  -0.1%    -228  [ = ]       0    .debug_line
  -0.0%    -108  [ = ]       0    TOTAL
use_config/nrf52840_ble_split (peripheral) — 316.6 KiB → 316.6 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 290252	   8508	  25472	 324232	  4f288	peripheral

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 290252	   8508	  25472	 324232	  4f288	peripheral

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%     +23  [ = ]       0    .debug_str
  +0.0%     +11  [ = ]       0    .debug_info
  +0.0%     +10  [ = ]       0    .debug_loc
  +2.8%      +2  [ = ]       0    [Unmapped]
  +0.0%      +1  [ = ]       0    .strtab
  -0.0%     -11  [ = ]       0    .debug_line
  +0.0%     +36  [ = ]       0    TOTAL
use_config/pi_pico_w_ble — 677.3 KiB → 677.3 KiB (+0.00% ⬇️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 639520	      0	  54056	 693576	  a9548	rmk-pi-pico-w

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 639524	      0	  54056	 693580	  a954c	rmk-pi-pico-w

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1% +5.03Ki  [ = ]       0    .debug_str
  +0.2%    +647  [ = ]       0    .strtab
  +0.0%    +105  [ = ]       0    .debug_info
  +0.0%     +10  [ = ]       0    .debug_loc
   +16%      +7  [ = ]       0    [Unmapped]
  +0.0%      +4  +0.0%      +4    .text
  -0.0%      -8  -0.0%      -8    .rodata
  -0.4%     -39  [ = ]       0    .debug_abbrev
  -0.0%     -73  [ = ]       0    .debug_line
  +0.1% +5.66Ki  -0.0%      -4    TOTAL
use_config/rp2040 — 146.1 KiB → 146.1 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 135700	      0	  13932	 149632	  24880	rmk-rp2040

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 135700	      0	  13932	 149632	  24880	rmk-rp2040

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1%     +97  [ = ]       0    .debug_line
  +0.0%     +61  [ = ]       0    .debug_info
  +3.5%      +2  [ = ]       0    [Unmapped]
  -0.0%     -10  [ = ]       0    .debug_loc
  -0.2%    -220  [ = ]       0    .strtab
  -0.1% -1.95Ki  [ = ]       0    .debug_str
  -0.1% -2.02Ki  [ = ]       0    TOTAL
use_config/rp2040_split (central) — 161.0 KiB → 161.0 KiB (+0.00% ⬇️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 149832	      0	  14996	 164828	  283dc	central

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 149836	      0	  14996	 164832	  283e0	central

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%     +29  [ = ]       0    .debug_info
  +0.0%     +17  [ = ]       0    .debug_line
  -0.0%      -4  -0.0%      -4    .text
  -0.0%      -6  [ = ]       0    .strtab
 -41.8%     -28  [ = ]       0    [Unmapped]
  -0.0%     -32  [ = ]       0    .debug_str
  -0.0%     -24  -0.0%      -4    TOTAL
use_config/rp2040_split (peripheral) — 27.9 KiB → 27.9 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
  25632	     60	   2876	  28568	   6f98	peripheral

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
  25632	     60	   2876	  28568	   6f98	peripheral

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%     +11  [ = ]       0    .debug_info
  +0.0%      +5  [ = ]       0    .debug_line
  -1.9%      -1  [ = ]       0    [Unmapped]
  -0.0%     -15  [ = ]       0    .debug_str
  [ = ]       0  [ = ]       0    TOTAL
use_config/stm32f1 — 62.4 KiB → 62.4 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
  57444	     28	   6396	  63868	   f97c	rmk-stm32f1

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
  57444	     28	   6396	  63868	   f97c	rmk-stm32f1

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%     +11  [ = ]       0    .debug_line
  +6.5%      +3  [ = ]       0    [Unmapped]
  +0.0%      +2  [ = ]       0    .debug_info
  +0.0%     +16  [ = ]       0    TOTAL
use_config/stm32h7 — 100.6 KiB → 100.6 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
  94580	    264	   8148	 102992	  19250	rmk-stm32h7

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
  94580	    264	   8148	 102992	  19250	rmk-stm32h7

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%     +63  [ = ]       0    .debug_str
  +0.0%      +9  [ = ]       0    .strtab
  -1.9%      -1  [ = ]       0    [Unmapped]
  -0.0%      -4  [ = ]       0    .debug_line
  -0.0%     -11  [ = ]       0    .debug_info
  +0.0%     +56  [ = ]       0    TOTAL
use_rust/nrf52832_ble — 379.6 KiB → 379.6 KiB (+0.00% ⬇️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 346152	   8620	  33936	 388708	  5ee64	rmk-nrf52832

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 346156	   8620	  33936	 388712	  5ee68	rmk-nrf52832

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1%    +249  [ = ]       0    .debug_line
  +0.0%    +153  [ = ]       0    .debug_info
  +0.0%     +32  [ = ]       0    .debug_loc
  +0.0%     +16  [ = ]       0    .debug_ranges
  +3.4%      +2  [ = ]       0    [Unmapped]
  -0.0%      -4  -0.0%      -4    .text
  -0.1%    -340  [ = ]       0    .strtab
  -0.1% -2.17Ki  [ = ]       0    .debug_str
  -0.0% -2.07Ki  -0.0%      -4    TOTAL
use_rust/nrf52840_ble — 428.9 KiB → 428.9 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 389316	   8628	  41256	 439200	  6b3a0	rmk-nrf52840

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 389316	   8628	  41256	 439200	  6b3a0	rmk-nrf52840

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1%    +219  [ = ]       0    .debug_line
  +0.0%      +9  [ = ]       0    .strtab
  +0.0%      +2  [ = ]       0    .debug_info
  +0.0%      +2  [ = ]       0    .debug_loc
  -4.8%      -3  [ = ]       0    [Unmapped]
  -0.0%      -9  [ = ]       0    .debug_str
  +0.0%    +220  [ = ]       0    TOTAL
use_rust/nrf52840_ble_split (central) — 493.7 KiB → 493.7 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 445312	   8668	  51536	 505516	  7b6ac	central

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 445312	   8668	  51536	 505516	  7b6ac	central

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%    +249  [ = ]       0    .debug_str
  +3.5%      +2  [ = ]       0    [Unmapped]
  -0.0%     -19  [ = ]       0    .strtab
  -0.0%    -135  [ = ]       0    .debug_info
  -0.1%    -233  [ = ]       0    .debug_line
  -0.0%    -136  [ = ]       0    TOTAL
use_rust/nrf52840_ble_split (peripheral) — 308.6 KiB → 308.6 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 282444	   8508	  25016	 315968	  4d240	peripheral

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 282444	   8508	  25016	 315968	  4d240	peripheral

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%     +11  [ = ]       0    .debug_info
  +0.0%      +5  [ = ]       0    .debug_str
  +4.3%      +2  [ = ]       0    [Unmapped]
  +0.0%      +1  [ = ]       0    .strtab
  -0.0%     -11  [ = ]       0    .debug_line
  +0.0%      +8  [ = ]       0    TOTAL
use_rust/pi_pico_w_ble — 676.7 KiB → 676.7 KiB (+0.00% ⬆️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 639200	      0	  53736	 692936	  a92c8	rmk-pi-pico-w

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 639192	      0	  53736	 692928	  a92c0	rmk-pi-pico-w

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%    +244  [ = ]       0    .debug_info
  +0.0%     +29  [ = ]       0    .debug_line
  +0.0%     +14  [ = ]       0    .strtab
  +0.0%      +8  [ = ]       0    .debug_str
  +0.0%      +8  +0.0%      +8    .text
 -12.5%      -7  [ = ]       0    [Unmapped]
  +0.0%    +296  +0.0%      +8    TOTAL
use_rust/rp2040 — 145.7 KiB → 145.7 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 135416	      0	  13764	 149180	  246bc	rmk-rp2040

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 135416	      0	  13764	 149180	  246bc	rmk-rp2040

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.1%    +141  [ = ]       0    .debug_line
  +0.0%     +61  [ = ]       0    .debug_info
  +9.4%      +5  [ = ]       0    [Unmapped]
  -0.2%    -220  [ = ]       0    .strtab
  -0.1% -1.97Ki  [ = ]       0    .debug_str
  -0.1% -1.98Ki  [ = ]       0    TOTAL
use_rust/rp2040_split (central) — 159.6 KiB → 159.6 KiB (+0.00% ⬇️)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 148720	      0	  14740	 163460	  27e84	central

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 148728	      0	  14740	 163468	  27e8c	central

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
   +15%      +8  [ = ]       0    [Unmapped]
  +0.0%      +4  [ = ]       0    .debug_info
  +0.0%      +4  [ = ]       0    .debug_line
  -0.0%      -2  [ = ]       0    .strtab
  -0.0%      -8  -0.0%      -8    .text
  -0.0%     -14  [ = ]       0    .debug_str
  -0.0%      -8  -0.0%      -8    TOTAL
use_rust/rp2040_split (peripheral) — 28.3 KiB → 28.3 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
  25740	     60	   3140	  28940	   710c	peripheral

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
  25740	     60	   3140	  28940	   710c	peripheral

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%     +11  [ = ]       0    .debug_info
  +8.1%      +3  [ = ]       0    [Unmapped]
  +0.0%      +2  [ = ]       0    .debug_line
  -0.0%      -1  [ = ]       0    .strtab
  -0.0%     -15  [ = ]       0    .debug_str
  [ = ]       0  [ = ]       0    TOTAL
use_rust/stm32f1 — 61.7 KiB → 61.7 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
  56804	     28	   6316	  63148	   f6ac	rmk-stm32f1

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
  56804	     28	   6316	  63148	   f6ac	rmk-stm32f1

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%      +9  [ = ]       0    .debug_line
  +0.0%      +2  [ = ]       0    .debug_info
  +2.2%      +1  [ = ]       0    [Unmapped]
  +0.0%     +12  [ = ]       0    TOTAL
use_rust/stm32h7 — 119.1 KiB → 119.1 KiB (+0.00%)

cargo size (PR):

   text	   data	    bss	    dec	    hex	filename
 107580	    320	  14052	 121952	  1dc60	rmk-stm32h7

cargo size (main):

   text	   data	    bss	    dec	    hex	filename
 107580	    320	  14052	 121952	  1dc60	rmk-stm32h7

Bloaty diff (PR vs main):

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  +0.0%      +2  [ = ]       0    .strtab
  -3.7%      -2  [ = ]       0    [Unmapped]
  -0.0%     -10  [ = ]       0    .debug_loc
  -0.0%     -35  [ = ]       0    .debug_info
  -0.0%    -117  [ = ]       0    .debug_str
  -0.1%    -122  [ = ]       0    .debug_line
  -0.0%    -284  [ = ]       0    TOTAL

@Schievel1
Schievel1 force-pushed the add-ext-DFU-flash branch 9 times, most recently from a769f40 to 93200eb Compare August 24, 2026 06:24
@Schievel1

Copy link
Copy Markdown
Contributor Author

I just found out I am lacking nrf52833 hardware to test this out. Because the BBC Microbit I bought is nrf52833, but it does not have a USB connector. The one USB socket is has is for the on board debugging chip apparently.
So either someone with nrf52833 hardware is willing to test this out, at least the noswap path, or we go with code review only.
The nrf52833 path is very similar to the nrf52840, in fact the only difference is the flash partitioning in the provided memory.x from rmk-boot: the 33 has 512kB flash and the 40 has 1MB.

@Schievel1
Schievel1 force-pushed the add-ext-DFU-flash branch 7 times, most recently from c5f6390 to d223fed Compare August 27, 2026 22:11
Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
@Schievel1

Copy link
Copy Markdown
Contributor Author

I think this is ready now. The one failing CI is because of the version mismatch of crate and what the test expects because you just released.

The noswap and nrf52833 path are just changes in the docs for RMK, that's why I included them in here. All users need to do is use the fitting memory.x

If someone happens to know a fitting w25q driver I would prefer the user to include it not to have it in this repo. I haven't found one.

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