Skip to content

flash-algorithm: add Verify support#28

Merged
9names merged 1 commit intorp-rs:mainfrom
xobs:add-verify-support
Dec 6, 2025
Merged

flash-algorithm: add Verify support#28
9names merged 1 commit intorp-rs:mainfrom
xobs:add-verify-support

Conversation

@xobs
Copy link
Contributor

@xobs xobs commented Dec 5, 2025

Add support for Verifying RP2040 and RP235x devices. These normally run with XIP flash disabled which means it's not possible to access the SPI flash as long as the algorithm is initialized.

Add support for Verifying RP2040 and RP235x devices. These normally run with
XIP flash disabled which means it's not possible to access the SPI flash as
long as the algorithm is initialized.

Signed-off-by: Sean Cross <sean@xobs.io>
Copy link
Member

@9names 9names left a comment

Choose a reason for hiding this comment

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

Change looks good to me, and I tested it with probe-rs run with both the --verify and --preverify flags and it worked.

But, probe-rs also worked with those flags (and faster) when I didn't use this algorithm with the verify code.
I'm pretty sure this never used to work. Maybe they now drop the algo between steps so it's memory mapped, and therefore this verify code isn't required for probe-rs?

@xobs
Copy link
Contributor Author

xobs commented Dec 6, 2025

If you interrupt the flashing process you’ll see that the verify step doesn’t work anymore since it leaves the xip flash disabled. I imagine it also wouldn’t work if you ran a program that disabled xip.

we might be able to improve performance by doing 32-bit accesses if it’s aligned, which it always should be.

@9names
Copy link
Member

9names commented Dec 6, 2025

I was also thinking about 32bit optimisation but was going to benchmark it before thinking about it any further. LGTM

@9names 9names merged commit 3e8e413 into rp-rs:main Dec 6, 2025
1 check passed
@9names
Copy link
Member

9names commented Dec 6, 2025

Did a quick check, u32 didn't really go much faster (at least in my naive impl)

without verify function

probe-rs download --verify --chip rp2040 --base-address 0x10001000 --binary-format bin 1mb.bin --speed 20000
      Erasing ✔ 100% [####################]   1.00 MiB @ 120.38 KiB/s (took 9s)
  Programming ✔ 100% [####################]   1.00 MiB @  84.96 KiB/s (took 12s)
    Verifying ✔ 100% [####################]   1.00 MiB @  47.03 KiB/s (took 22s)
Finished in 42.44s

8bit verify

probe-rs download --verify --chip rp2040 --base-address 0x10001000 --binary-format bin 1mb.bin --speed 20000
      Erasing ✔ 100% [####################]   1.00 MiB @ 120.16 KiB/s (took 9s)
  Programming ✔ 100% [####################]   1.00 MiB @  84.92 KiB/s (took 12s)
    Verifying ✔ 100% [####################]   1.00 MiB @  40.70 KiB/s (took 25s)                                                                               Finished in 45.84s

8/32bit verify

probe-rs download --verify --chip rp2040 --base-address 0x10001000 --binary-format bin 1mb.bin --speed 20000
      Erasing ✔ 100% [####################]   1.00 MiB @ 119.02 KiB/s (took 9s)
  Programming ✔ 100% [####################]   1.00 MiB @  84.94 KiB/s (took 12s)
    Verifying ✔ 100% [####################]   1.00 MiB @  42.81 KiB/s (took 24s)                                                                               Finished in 44.68s
if address % 4 == 0 && size % 4 == 0 {
    // the start address and the size of the data are u32 aligned, use u32 for speed
    let (check, data) = unsafe {
        (
            core::slice::from_raw_parts(address as *const u32, size as usize),
            // making the assumption that data would be 32bit aligned so .0 and .2 are empty - seems to work...
            data.align_to::<u32>().1,
        )
    };

    for (offset, (check, data)) in check.iter().zip(data.iter()).enumerate() {
        if *check != *data {
            let mut offset = offset * 4;
            let data_bytes = data.to_le_bytes();
            let check_bytes = check.to_le_bytes();
            for i in 0..4 {
                if data_bytes[i] != check_bytes[i] {
                    break;
                }
                offset += 1;
            }
            (self.funcs.flash_exit_xip)();
            // Return the first address that failed.
            return ErrorCode::new(offset as u32 + address)
                .map(|e| Err(e))
                .unwrap_or(Ok(()));
        }
    }
} else { // the code in PR 28

@xobs xobs deleted the add-verify-support branch December 6, 2025 07:49
@xobs
Copy link
Contributor Author

xobs commented Dec 6, 2025

I really do wish it were faster. Thanks for checking that avenue. My concern with this patch was mostly on reliability and making it always work, and this dues increase reliability when doing a preverify after flashing has been interrupted. Your patch seems slightly faster, but it’s still not as good as direct memory access.

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