Skip to content

Upgrade the nRF51 bootloader and softdevice when flashing - #24

Open
evoggy wants to merge 5 commits into
mainfrom
evoggy/nrf51-softdevice-upgrade
Open

evoggy wants to merge 5 commits into
mainfrom
evoggy/nrf51-softdevice-upgrade

Conversation

@evoggy

@evoggy evoggy commented Oct 2, 2026 •

Copy link
Copy Markdown
Member

Release archives carry a combined nRF51 bootloader+softdevice binary
(type: bootloader+softdevice, provides: [sd-s130]), and the nRF51 firmware
declares which softdevice it needs (requires: [sd-s130]). cflib uses this to
move older Crazyflies from S110 to S130 as part of a normal flash. cfcli ignored
the bundle, so it could not bring a Crazyflie that is still on S110 up to date.

bootload flash now flashes the bundle first when it is needed, then the rest
of the archive. A Crazyflie that still needs it usually runs firmware too old
for this cfcli to connect to, so it is flashed cold, as the hint from #21
suggests.

When the bundle is flashed

The softdevice on the device is worked out from where its bootloader says the
firmware starts (page 88 = S110, 108 = S130). The bootloader version comes from
the info packet.

  • The firmware needs a softdevice that neither the device nor the archive has:
    error, nothing is flashed.
  • The device runs S110 and the archive provides S130: flash.
  • The device runs S130 and the archive provides S110: refused. Upgrades only
    go forwards, so cfcli never needs to carry an old softdevice.
  • Same softdevice: flash only if the archive's bootloader release is newer than
    the device's. The original bootloader reports no version and counts as older
    than anything.
  • A bundle given with --bin nrf51-bootloader+softdevice=<file> has no release
    version and is always flashed, after a confirmation (below).

If the upgrade is refused, the Crazyflie is restarted into its firmware rather
than left in the bootloader.

Flashing it

This follows cflib:

  1. Erase the first page of the nRF51 firmware. A bootloader update interrupted
    half-way then stays in bootloader mode instead of jumping into a partly
    overwritten firmware.
  2. Write the bundle so that it ends at the last page the bootloader can write.
  3. Restart into the bootloader and follow it to its own address.
  4. Re-read the bootloader info, since the flash layout moves with the
    softdevice. The nRF51 firmware from the same flash is then written at the new
    start page.

nrf51-bootloader+softdevice is added to the list of flash targets.

Confirming a bootloader from a file

A bundle from a release or zip is a released bootloader, but one given with
--bin can be anything. If it does not start, the Crazyflie can no longer be
flashed over the radio and can only be recovered with an SWD debug probe. So
bootload flash and swarm bootload flash warn and ask before flashing one
(default no; once for the whole swarm). --accept-bootloader-risk flashes it
without asking and is required when running non-interactively (exit code 30
without it). Releases and zips are flashed without asking.

Depends on bitcraze/cfloader-rs#2

This uses the bootloader version, reset_to_bootloader() and refresh_info()
from that PR. Cargo.toml points at its branch for now and should go back to a
crates.io release once one is published.

Testing

  • cargo test: unit tests cover the bundle decision for a --bin bundle, a
    current release and a newer release, and when the confirmation is needed.
  • The S110 → S130 path was run end to end before rebasing onto current main:
    a Crazyflie 2.1 downgraded to S110 (2023.11) was upgraded to 2026.08 over a
    cold boot (see Report the bootloader version and restart into a new bootloader cfloader-rs#2).
  • Before this rebase the --bin bundle path put a development nRF51
    bootloader on eight Crazyflie 2.1 Brushless, with the bootloader's flash CRC
    checked against the file afterwards.
  • The non-interactive refusal without --accept-bootloader-risk was run; the
    interactive prompt has not been exercised on hardware.

evoggy added 5 commits October 7, 2026 20:39
The softdevice upgrade needs the bootloader version, reset_to_bootloader()
and refresh_info() from bitcraze/cfloader-rs#2, which is not released yet.
Point at the PR branch instead of a local path so the branch builds
anywhere; switch back to a crates.io release once it is out.
A bundle passed with --bin has no release version, only "custom", which
does not parse. The version comparison treated that as unknown and
skipped the bundle whenever the device's bootloader reported a version,
so the flash reported success without writing anything. A --bin bundle
is an explicit request and is now flashed whatever the device runs.
The softdevice upgrade made --platform skip reading the platform from the
firmware on a warm flash too, for Crazyflies whose firmware is too old to
connect to. Such a Crazyflie is flashed cold instead, which is what the
protocol mismatch hint recommends, so go back to using --platform only
together with --cold.
A bootloader+softdevice from a release or zip is a released one, but one
given with --bin is always flashed and can be anything. If it does not
start, the Crazyflie can no longer be flashed over the radio and can only
be recovered with an SWD debug probe, so bootload flash and swarm bootload
flash now ask first (default no, once for the whole swarm).

--accept-bootloader-risk flashes it without asking and is required when
running non-interactively. The target, the prompt and the flag are
documented in docs/bootload.md.
@evoggy
evoggy force-pushed the evoggy/nrf51-softdevice-upgrade branch from 13e3cdc to faf37ef Compare October 7, 2026 18:44
@evoggy

evoggy commented Oct 9, 2026

Copy link
Copy Markdown
Member Author

This fixes #15

This branch has not been deployed

No deployments
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.

1 participant