tillitis-key/hw/boards/tp1/firmware/README.md

6.7 KiB

Ice40 programmer

This firmware allows a Raspberry Pi Pico (or any RP2040) to work as a programmer for the lattice ice40 parts.

It has been integrated into icestorm: https://github.com/tillitis/icestorm/commits/interfaces

Advantages:

  • Cheap: RPi Pico boards are currently EUR4, FT232H boards are closer to EUR15
  • Available: As of summer '22, FT232H boards and chips are in short supply; Pico boards are still readily available
  • Flexible: Any GPIO-capable pins on the pico can be used for programming. This allow for example multiple ice40 parts to be programmed from a single Pico.

Usage

First, program your RPi Pico using the included binary 'main.u2f'. To do so, disconnect the pico from your computer, press down the bootloader button, then plug the pico back in. The computer should detect it as a memory device. Copy the main.u2f file into the root directory of this memory device. This will program the Pico. Once completed, the pico should restart and present itself as a USB HID device.

To use it with icestorm, the 'iceprog' utility will need to be built from the above fork. Known issues:

  • This version of iceprog is hard-coded to use the pico as a programmer; it should have a command-line switch to choose the correct programmer
  • SRAM programming mode (-S) is untested

TODO: Suggested wiring diagram

TODO: Permissions

Version checking

The firmware version can be determined from the bcdDevice field in the USB device descriptor. Known versions are:

bcdDevice Version Description
0x0100 1.0 Raw USB test version
0x0200 2.0 Release version

The command set described in this document describes the version 2.0 format.

Command set

Commands are sent to the device as control transfers. The bRequest field is used to select the commmand, and any configuration data associated with the command

Command Direction bRequest wValue wIndex wLength
Set pin directions OUT 0x30 0 0 8
Set pullups/pulldowns OUT 0x31 0 0 12
Set pin values OUT 0x32 0 0 8
Get pin values IN 0x32 0 0 4
Configure SPI pins and clock speed OUT 0x40 0 0 5
Perform a SPI transfer OUT 0x41 0 0 5+n
Read data from previous SPI transfer IN 0x41 0 0 n
Send SPI clocks OUT 0x42 0 0 0
Read ADC inputs IN 0x50 0 0 12
Enter bootloader mode OUT 0xE0 0 0 0

Additionally, the device supports an additional control transfer to support driver assignment on Windows:

Command Direction bRequest wValue wIndex wLength Description
MS_DESCRIPTOR IN 0xF8 0 0 x Get a Microsoft OS compatible descriptor

Set pin directions

This command is used to set pin directions. The first field is a mask of pins to update, and the second is a bitmap of the resulting states. Any pin that has a bit set in the mask will be updated.

Data packet format:

Offset Length Description
0x00 4 uint32: Pin mask (1=set direction)
0x04 4 uint32: Pin direction (1=output, 0=input)

Set pin pullup/pulldown resistors

This command is used to set pin pullup/pulldown resistors. The first field is a mask of pins to update, the second is the pull-up states, and the third is the pull-down states. Any pin that has a bit set in the mask will be updated.

Data packet format:

Offset Length Description
0x00 4 uint32: Pin mask (1=set direction)
0x04 4 uint32: Pin pullups (1=enable, 0=disable)
0x08 4 uint32: Pin pulldowns (1=enable, 0=disable)

Set pin values

This command is used to set the value of output pins. The first field is a mask of pins to update, and the second is a bitmap of new output values to apply. Any pin that has a bit set in the mask will be updated.

Data packet format:

Offset Length Description
0x00 4 uint32: Pin mask (1=set direction)
0x04 4 uint32: Pin value (1=high, 0=low)

Read pin values

This command is used to read the value of all pins. Note that pins which are confgured as outputs will report their current output setting.

Data packet format:

Offset Length Description
0x05 4 uint32: Pin values (1=high, 0=low)

Set SPI configuration

This command is used to configure the SPI engine.

Data packet format:

Offset Length Description
0x00 1 GPIO pin number for SCK
0x01 1 GPIO pin number for CS
0x02 1 GPIO pin number for MOSI
0x03 1 GPIO pin number for MISO
0x04 1 SPI clock frequency, in MHz

Transfer SPI data

This command is used to send data over the pins currently configured as the SPI interface. This command performs a full-duplex read/write operation, and stores the read data in a buffer. To retrieve the data read during this operation, issue a read command.

Data packet format:

Offset Length Description
0x00 1 0: don't toggle CS; any other value: toggle CS
0x01 4 Bytes to transfer
0x05 1-2040 SPI data to transfer

Get data read during previous SPI transaction

This command is used to retrieve any data transferred during the previous SPI transaction.

Data packet format:

Offset Length Description
0x00 1-2040 SPI data to transfer

SPI clock out

This command is used to toggle the SPI clock pin, but doesn't transfer any data.

Data packet format:

Offset Length Description
0x00 4 Number of SPI bytes to clock

Read ADCs

This command is used to read the analog value of analog input pins 0-2. Each value is returned as a uint32_t value representing the reading in microvolts.

Data packet format:

Offset Length Description
0x01 4 ADC channel 0 value, in microvolts
0x05 4 ADC channel 1 value, in microvolts
0x09 4 ADC channel 2 value, in microvolts

Bootloader

This command is used to put the device in bootloader mode. No data is sent during this

Building the firmware

First, follow the details in the toolchain setup document to install the Raspberry Pi Pico SDK. Then, the firmware can be built by running the build script:

./build.sh

Once complete, the output binary is located in build/main.uf2