iCEBlaster is a Drag and Drop firmware loader via SPI for iCE40LP1K and iCE40UL1K. The brain of this project is based on STM32F103CBT6 Arm Cortex M3 microcontroller sitting on the Maple Mini stm32 dev board.
How it works?
By using USB-FS library working as USB Mass storage device class (USB MSC) and with interface I/O code with internal Flash. Working together as USB Disk pre formatted with FAT12 file system with 1024 Bytes per sector, 64total sectors, 3 sectors reserved for master boot record (sector 0) and File allocation tables(sector 1-2). And using total of 64 internal Flash pages (1Kbytes per page, page 64 to 127, total of 64KBytes).
By copying the iCE40 FPGA Bitstream to the disk, 2 while loops help to locate the physical address of Bitstream on the internal Flash (for spi tx pointer) and to figure out the Bitstream size (for spi tx size). After that the Bitstream loading sequence begin.
When done, The mcu release CRESET to let FPGA run the firmware that we just flash. Then perform the internal flash reformat to have a new and ready to Drag and Drop USB Disk.
with while loop and nested if-statement to check for magic word (or preamble) 0x7EAA997E. This is the beginning of the Bitstream. Another while loop check for 0x010600 which indicates the end of Bitstream (and It's actually a wake up command to wake the iCE40 up).
Bitstream Loading sequence.
// Enter Slave SPI mode.
1. Set SPI CE pin to LOW.
2. Set CRESET pin to LOW.
3. Wait for 2ms.
4. Set CRESET pin to HIGH.
5. wait for 200ms to let CRAM clear itself.
// Send Bitstream
6. Send Bitstream Via SPI, 8 bit and MSB first.
7. Send additional 12 dummy bytes (96 clock cycles).
8. (optional) send additional 7 dummy (56 clock cycles), this will allow to reuse SPI pins as user PIO.
// End of Bitstream loading.
9. Set SPI CE pin to HIGH.