Skip to content

HowTo FuPy on iCE40 Boards

Jan Schmidt edited this page Jan 19, 2019 · 21 revisions

FuPy on iCE40 Boards

Introduction

This how-to guide is for people who want to get started running MicroPython on a iCE40 based development board using FμPy.

The process for booting either board is extremely similar, so this guide combines the two.

By the end of this guide you will have a MicroPython REPL running on the board's FPGA using a Soft CPU.

You will need:

  • A laptop running Linux, or a Linux VM (Ubuntu 16.04 LTS is well tested)
  • A USB cable to connect the FPGA board to your laptop

This guide will show you how to;

This guide uses Ewen McNeill's corresponding wiki page for the Arty A7 as a basis.

All shell commands in this guide use bash

Supported Boards

Tier 1

Tier 1 boards can be used without any physical modification to the board and provide a great experience.

The icebreaker is an ideal board to play with FuPy. It has the iCE40UP5K, user buttons + LEDs and a serial UART.

You will need;

  • A micro USB cable to connect the Icebreaker to your laptop.

Tier 2

Tier 2 boards can be used without any physical modification but have some type of limiting factor that prevents an awesome experience.

The HX8K only has limited RAM for MicroPython.

You will need;

  • A mini USB cable to connect the TinyFPGA BX to your laptop.

Tier 3

Tier 3 boards require extra components or modification to the board to be used.

The TinyFPGA BX has the USB pins directly connected to the FPGA. This means special functionality is required inside the FPGA design for the USB connection to operate. At this time, this functionality has not been integrated into the LiteX-BuildEnv environment thus you will require a seperate UART interface to see the MicroPython prompt.

You will need;

In addition, you may wish to pick up one or more of the following items:

Hardware Modification Needed

You will need to connect the USB UART to the following pins (marked on TinyFPGA's silkscreen):

TinyFPGA Pmod USBUART Adafruit Cable
G (GND) Pin 5 (GND) Black Wire (GND)
1 (TX) Pin 3 (RX) Green Wire (RX)
2 (RX) Pin 2 (TX) White Wire (TX)

Below are photos of connections in both cases:

  • Pmod USB UART attached to TinyFPGA BX using Pmod BB: Pmod USB UART attached to TinyFPGA BX using Pmod BB

  • USB-to-Serial Cable attached to TinyFPGA via male headers and Pmod BB USB-to-Serial Cable attached to TinyFPGA via male headers and Pmod BB

You will need;

Hardware Modification Needed

You will need to do the following;

  • Solder the pin headers onto the PMOD socket.
  • Connect the Pmod USBUART Interface to the bottom row of the PMOD socket.

Configure USB Connection

First we need to configure how we connect with the device by creating some rules for udev:

git clone https://github.com/timvideos/HDMI2USB-mode-switch.git
cd HDMI2USB-mode-switch/udev
make install
make reload

Next we ensure that your user has permission to access the relevant device files:

sudo adduser $USER video
sudo adduser $USER dialout       # or 'uucp' group on some Linux distros
sudo reboot

(or on Fedora, use sudo usermod $USER -a -G video,dialout then sudo reboot)

(if you do not want to reboot it is sufficient to log your user out, and back in again; use id to check that your user is in the correct groups, particularly dialout or uucp).

Download the Build Environment

Next we download and setup the build environment. This environment contains the tools that we need to build the gateware + firmware and load them onto the FPGA.

git clone https://github.com/timvideos/litex-buildenv.git
cd litex-buildenv/

# Build targets
export CPU=lm32             # Soft CPU architecture
export CPU_VARIANT=minimal  # Use a resource-constrained variant to make up5k happy
export PLATFORM=icebreaker  # Target platform Icebreaker, or PLATFORM=tinyfpga_bx for TinyFPGA BX
export FIRMWARE=micropython
export TARGET=base

# Download dependencies for the build environment
./scripts/download-env.sh

Enter the build environment

Once the download is done (several minutes) you can enter your build environment. You will need to do this every time you use the litex build tools (eg, in a new terminal window or a new login). The environment variable settings are the same as above (substituting PLATFORM=tinyfpga_bx if you are using that board).

export CPU=lm32
export CPU_VARIANT=minimal
export PLATFORM=icebreaker
export TARGET=base
export FIRMWARE=micropython

source scripts/enter-env.sh

Compiling the Gateware and BIOS

Both the Icebreaker and TinyFPGA BX boards use a fully open source flow to build the FPGA gateware. The tools are:

For this tutorial, we will be building our own gateware. The download-env.sh script will have downloaded the above tools for you. To make the gateware, run the following from the root of litex-buildenv (assuming you have already entered the build environment as described above):

make gateware

The above command will compile a set of base C libraries, a BIOS, and then generate the FPGA bitstream. After this command is finished, we still need to compile Micropython. However, first we should test whether the gateware and soft-CPU function properly.

Loading the gateware onto the Icebreaker

While some platforms on litex-buildenv support loading the gateware (along with a BIOS embedded into the BRAM) into volatile memory for testing, on the Icebreaker and TinyFPGA BX, the gateware and the BIOS must be written to SPI flash.

To flash the gateware and the BIOS at once, use the following command:

make gateware-flash

On Icebreaker, the output will be sent through the USB serial console.

Currently TinyFPGA BX requires an external UART and connected as following;

  • Data from external device to the FPGA, should be connected to Pin 1 (as labeled on the TinyFPGA BX silkscreen).
  • Data to external device from the FPGA should be connected to Pin 2 (as labeled on the TinyFPGA BX silkscreen).

For the TinyFPGA BX set COMM_PORT to the USB serial port of the USB serial device you are using (since this is your own USB serial device it cannot be auto-assigned), and run make firmware-connect, eg:

export COMM_PORT=/dev/ttyUSB0     # Or whatever your USB serial device is recognised as
make firmware-connect

Either way, once the output pauses in the serial console, hit the enter key, you should see a BIOS> prompt. Type help and enter for a list of commands to test the BIOS out.

(If you get a "Failure!" programming the TinyFPGA BX with the gateware only, this may possibly be related to a file size length related tinyprog issue -- see https://discourse.tinyfpga.com/t/issues-with-tinyprog-u-on-bx/628/11 -- which should be fixed by using tinyprog 1.0.23 or later. If you get told there is no active bootloader, either press the reset button on the TinyFPGA BX and wait a few seconds for the boot loader to initialise, or unplug / plug in the TinyFPGA BX to power cycle it. The TinyFPGA BX will normally sit in the boot loader when first powered on if it is connected to a USB host; you can exit the boot loader with "tinyprog -b" if you want to run the previously installed application.)

Building and running MicroPython (FμPy)

Next we will build the MicroPython firmware and load it onto the soft CPU:

./scripts/build-micropython.sh
make image-flash

You can also use make image to just create the combined gateware, BIOS, and micropython image that will be programmed onto the SPI flash of either board. In this case, the output image will be available under:

  • build/icebreaker_base_lm32.minimal/image-gateware+bios+micropython.bin for Icebreaker, and
  • build/tinyfpga_bx_base_lm32.minimal/image-gateware+bios+micropython.bin for TinyFPGA BX

Once the image has been flash to the boards using make image-flash or otherwise, the BIOS should detect a valid image and should start booting MicroPython.

At this point connect to the serial console, as above, and wait. Eg, for the TinyFPGA BX:

export COMM_PORT=/dev/ttyUSB0     # Or whatever your USB serial device is recognised as
make firmware-connect

After approximately 20 seconds (we are running a program from SPI flash on a CPU with no cache, after all) you should reach a MicroPython REPL:

Booting from serial...
Press Q or ESC to abort boot completely.
sL5DdSMmkekro
Timeout
Booting from flash...

        __   _ __      _  __
       / /  (_) /____ | |/_/
      / /__/ / __/ -_)>  <
     /____/_/\__/\__/_/|_|
 SoC BIOS / CPU: LM32 /  12MHz
(c) Copyright 2012-2018 Enjoy-Digital
(c) Copyright 2007-2018 M-Labs Limited
Built Nov  8 2018 01:55:19

BIOS CRC passed (1055eedc)
Booting from serial...
Press Q or ESC to abort boot completely.
sL5DdSMmkekro
Timeout
Booting from flash...
Executing booted program at 0x20028008
MicroPython v1.9.4-533-g7b0c4384b on 2018-11-08; litex with lm32
>>> 

Try running the following program and see if you can get an LED to blink! Type one line at a time at the REPL, as sometimes serial chars can arrive too fast on these boards:

import litex

l = litex.LED(1)

while True:
    l.on()
    l.off()
Clone this wiki locally