Bootloader¶
- class squishy.gateware.bootloader.SquishyBootloader(*args: Any, src_loc_at: int = 0, **kwargs: Any)¶
Squishy DFU Bootloader
This is the “top” module representing a Squishy DFU capable bootloader.
It provides DFU alt-modes for each flash slot, including the bootloader, as well as dispatch to the appropriate programming interface for the given platform.
For
SquishyRev1
platforms, the method of programming is direct SPI flash, followed by an SB_WARMBOOT trigger.For
SquishyRev2
this is more complicated, as we have the supervisor MCU in the mix. First the image is written to the SPI PSRAM, a signal is then sent to the supervisor to reboot us and re-program us with the new bitstream.Note
There needs to be some consideration for hardware platforms that support ephemeral programming, any transfers to that slot must be distinguished from a normal slot transfer, for Rev1 platforms this is not an issue, as there is no way of doing an ephemeral applet, however for Rev2, in order to try to tide wearing out flash with write cycles (even though they’re good for like, 100k cycles) we have an (optional?) onboard PSRAM that acts as both a cache for doing flash updates as well as doing hot-loading without actually touching flash.
This can be done mostly opaquely from the root of the bootloader module itself, other than having to properly name the ephemeral DFU slot, as all the machinery for updating the platform is within the target module for that anyway.
Warning
Currently there is no flash protection for the bootloader slot (slot 0), it is exposed by default, and treated like any other applet slot.
We also don’t have any checksums, which might be a bit problematic, but due to some platform limitations specifically due to Rev1 where we write directly into flash and don’t have a buffer that can be used and discarded, we write-over the slot as we update. This is particularly dangerous for the bootloader.
- class squishy.gateware.bootloader.rev1.Rev1(*args: Any, src_loc_at: int = 0, **kwargs: Any)¶
- Parameters:
fifo (AsyncFIFO | None) – The storage FIFO.
- Variables:
trigger_reboot (Signal) – Input: FPGA reboot trigger from DFU.
slot_selection (Signal(2)) – Input: Flash slot destination from DFU alt-mode.
dl_start (Signal) – Input: Start of a DFU transfer.
dl_finish (Signal) – Input: An acknowledgement of the dl_done signal
dl_ready (Signal) – Output: If the backing storage is ready for data.
dl_done (Signal) – Output: When the backing storage is done storing the data.
dl_size (Signal(16)) – Input: The size of the DFU transfer into the the FIFO
slot_changed (Signal) – Input: Raised when the DFU alt-mode is changed.
slot_ack (Signal) – Output: When the slot_changed signal was acted on.
Squishy Supervisor Bootloader Protocol:
If we are in an applet and wish to drop into the bootloader:
FPGA raises ~SU_IRQ with the IRQ register value DFU set to 1
Supervisor resets the FPGA configuration and loads the bootloader bitstream
Supervisor then waits for the next IRQ event
Supervisor then checks the IRQ register to make sure it is in_boot
When the FPGA enters bootloader:
- FPGA waits for a DFU upload, and if done stuffs it into the PSRAM
FPGA sticks the destination slot for the DFU payload into the dest_slot half of the slots register
FPGA writes the DFU payload size into the txlen register
FPGA sets the IRQ Reason to `in_boot`*
FPGA raises the ~SU_IRQ line to notify the supervisor we are in the bootloader*
- Supervisor reads the slots and txlen registers
- If the destination slot is not ephemeral:
Supervisor erases the flash region mapped to that slot
Supervisor write the contents of the PSRAM for txlen into the target flash slot
Supervisor then writes into the FPGA control register that the erase/flash cycle is done
Supervisor waits for the FPGA to tell it to reboot into a given slot
FPGA triggers reboot on DFU detach to last written slot?
- If the destination slot is ephemeral:
Supervisor resets the FPGA into configuration mode
Read a block into our SPI buffer from the PSRAM
- While we have not written the full bitstream:
α. Read at most buffers worth of bitstream data from PSRAM β. Dump buffer into FPGA configuration
Check FPGA configuration status
let the FPGA boot into new bitstream
- class squishy.gateware.bootloader.rev2.Rev2(*args: Any, src_loc_at: int = 0, **kwargs: Any)¶
- Parameters:
fifo (AsyncFIFO | None) – The storage FIFO.
- Variables:
trigger_reboot (Signal) – FPGA reboot trigger from DFU.
slot_selection (Signal(2)) – Flash slot destination from DFU alt-mode.
dl_start (Signal) – Input: Start of a DFU transfer.
dl_finish (Signal) – Input: An acknowledgement of the dl_done signal
dl_ready (Signal) – Output: If the backing storage is ready for data.
dl_done (Signal) – Output: When the backing storage is done storing the data.
dl_reset_slot (Signal) – Input: Signals to the storage to reset the active slot.
dl_size (Signal(16)) – Input: The size of the DFU transfer into the the FIFO
slot_changed (Signal) – Input: Raised when the DFU alt-mode is changed.
slot_ack (Signal) – Output: When the slot_changed signal was acted on.