feat(dfu_split): Embassy boot flash peripheral from central #886
feat(dfu_split): Embassy boot flash peripheral from central #886Schievel1 wants to merge 1 commit into
Conversation
4fe7d4c to
5ce436b
Compare
82f55ac to
f8cac52
Compare
396b095 to
6a9363b
Compare
Size Report
|
… central Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
6a9363b to
f667f20
Compare
|
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? |
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 0we flash the central. If we rundfu-util -D ./peripheral.bin -a 1we 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 3etc.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:
Central runnnig, peripheral starts up:
The AI overlords drew this for me, all hail to the AI overlords: