Sunday, March 29, 2020

LiteX Soft CPU on the ULX3S - reloading firmware without reflashing the soft CPU

My next post (aka notes to self) on getting a RISC-V compiled app onto the ULX3S using LiteX.

TL;DR; press the reset button!

Quite a diversion from my day job with SQL and C# and web apps is this fascinating world of soft CPU's and embedded devices. Here's what I learned this weekend:

In my prior blogs, I considered getting Circuit Python running on the ULX3S. There are a lot of moving parts, so I got started with implementing the RISC-V soft CPU on the FPGA. Recall we cannot run Circuit Python on the ESP32 because of hardware limitations (missing USB OTG), however the ESP32-S2 will (in theory) work with Circuit Python. Next, I rambled on a bit regarding various features of LiteX that I was exploring in my prior blog, in the end creating a soft_cpu.sh script with everything I learned.

Refresher:  Onboard the ULX3S is an ECP5 FPGA. We first need to create a soft CPU bitstream that is loaded onto the ECP5LiteX also creates a BIOS that gets loaded over the serial port. Ok, all fine and dandy, but I seem to only be able to load that BIOS once and then the terminal becomes unresponsive. This makes sense, as the processor stays in the while loop after liftoff. The bios does not appears to be an RTOS.

ULX3S shown with FPGA/BIOS/firmware programming USB cable

Supposedly that BIOS should be able to reload firmware apps. Well, there's this mystery boot_helper. What does this extern do? I suspect that's what loads the BIOS. Then what? There's this 4 line boot-helper-picorv32.S file. Not much help there. The "What is LiteX" introduction does seem to indicate that the development cycle includes reloading the soft CPU, as the "design flow in a nutshell" indicates going back to step 1. I'd like to go back to step 6, skipping the re-synthesis of the soft CPU every time I change the firmware.

The LiteX for the ULX3S has a serial port configured as Tx on Pin L4 (FTDI RxD) and Rx on Pin M1 (FTDI TxD). See the schematic. These pins are not available on either of the external ULX3S headers.

FTDI RxD/TxD USB Serial on ULX3S FPGA pins L4 and M1
I had thought perhaps the BIOS would be looking on a pair of pins implemented in the FPGA as a serial port. Nope. Those pins are definitely hard wired the the FTDI USB serial port.

So what else is there? Well, the BIOS is clearly not an RTOS. So we're definitely waiting forever and doing nothing in that while (1) statement. How else does a CPU begin again? Reset of course! Check out the rst implementation in LiteX. It is hooked to R1 of the FPGA. What's that?

R1 (aka BTN_F1) on the ULX3S
That's the F1 button!! (The "Fire 1" position when the ULX3S is in gamer mode! lol). This is also labeled as "B1" on the PCB, located near the SD card, right under the text "2.5V/3.3V"

It turns out the architecture is not [CPU] - [BIOS] - [firmware]. Instead, the simpler: [CPU (with tiny, baked in BIOS] - [BIOS (with external firmware)].  Now, one could certainly write something in the BIOS to, say load an OS. But that's not what LiteX is doing out of the box in this example.

The architecture naming is a bit misleading, as there is part of the CPU implemented as a BIOS as seen at processor boot time on the LiteX. Unfortunately the external "C" program is also called BIOS (firmware).



So just leave litex_term running and press the F1 (CPU reset) button to reload the BIOS firmware. See my soft_cpu.sh bash script. Each time you update and compile the BIOS code, press the F1 button to reload it onto the soft CPU.

I've created LiteX Pull Request #445 that adds some comments to hopefully help others that may encounter these issues.

How many times can an FPGA be reprogrammed? Well, the folks at Numato claim "SRAM based FPGAs can be programmed as many times as necessary. There is no limit..."

There's also the possibility of using a logic analyzer internally to the FPGA. Also mentioned in the What is LiteX is something called litescope. See the Debugging with ChipScope for more information, as there's not much in the Wiki as of the data of this blog. The architecture image provides some insight. See also the test_analyzer.py.

So now.. I wonder if I can single-step code soft CPU code with OpenOCD. And that litescope! That sounds super interesting...

Saturday, March 28, 2020

RISC-V on the ULX3S with LiteX - Part 2

First .. the exciting news: With 24 days still left in the Crowd Funding Campaign, the ULX3S is within a few dollars of reaching their $40K stretch goal!! I'm so happy to see their success. I've been super happy with mine. (Edit: now nearly 300% funded by the time I publish this!)

TL;DR: Check out this soft_cpu.sh script used to create a soft RISC-V CPU on the ULX3S.

Back to my fomu! I revisited the Adafruit Feather M0 Express - A request for the USB device descriptor failed: Issue #293 on GitHub in the hathach/tinyusb repo. The suggestion was to simply update my fomu to see if the Feather M0 problems would go away:

The last few lines of the release.sh
dfu-suffix -v 1209 -p 70b1 -a $output/${platform}-updater-${release}.dfu
dfu-suffix -v 1209 -p 70b1 -a $output/${platform}-foboot-${release}.dfu
but I saw an error when trying to do that:
C:\Download\dfu-util>dfu-suffix -v 1209 -p 70b1 -a fomu\hacker-updater-v2.0.3.dfu
dfu-suffix (dfu-util) 0.9

Copyright 2011-2012 Stefan Schmidt, 2013-2014 Tormod Volden
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

Please remove existing DFU suffix before adding a new one.
so I next tried using dfu-util, as noted here:
C:\Download\dfu-util>dfu-util -D fomu\hacker-updater-v2.0.3.dfu
dfu-util 0.9

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2016 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

Match vendor ID from file: 1209
Match product ID from file: 70b1
Opening DFU capable USB device...
ID 1209:5bf0
Run-time device DFU version 0101
Claiming USB DFU Interface...
Setting Alternate Setting #0 ...
Determining device status: state = dfuIDLE, status = 0
dfuIDLE, continuing
DFU mode device DFU version 0101
Device returned transfer size 1024
Copying data from PC to DFU device
Download        [=========================] 100%       112828 bytes
Download done.
state(7) = dfuMANIFEST, status(0) = No error condition is present
state(8) = dfuMANIFEST-WAIT-RESET, status(0) = No error condition is present
Done!

Since that seems to have been successful, I will return to the ULX3S for now.

A quick check of the rxrbln/picorv32 ULX3S fork that is is included in my full toolchain install and I'm still not yet able to build:

gojimmypi@ubuntu:~/workspace/rxrbln-picorv32/picosoc$ git fetch
gojimmypi@ubuntu:~/workspace/rxrbln-picorv32/picosoc$ git pull
Already up to date.
gojimmypi@ubuntu:~/workspace/rxrbln-picorv32/picosoc$ make
iverilog -s testbench -o hx8kdemo_tb.vvp hx8kdemo_tb.v hx8kdemo.v spimemio.v simpleuart.v picosoc.v ../picorv32.v spiflash.v `yosys-config --datdir/ice40/cells_sim.v`
picosoc.v:70: error: NULL port declarations are not allowed.
Makefile:20: recipe for target 'hx8kdemo_tb.vvp' failed
make: *** [hx8kdemo_tb.vvp] Error 1
gojimmypi@ubuntu:~/workspace/rxrbln-picorv32/picosoc$ 

So ok, I'll give that one some more time.

Refresher on getting Micropython onto the fomu:
cd /mnt/c/workspace
mkdir -p fomu
cd fomu
wget https://github.com/im-tomu/fomu-workshop/raw/master/micropython-fomu.dfu
dfu-util -D micropython-fomu.dfu
Should give an output like this:
dfu-util 0.9

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2016 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

Match vendor ID from file: 1209
Match product ID from file: 5bf0
Opening DFU capable USB device...
ID 1209:5bf0
Run-time device DFU version 0101
Claiming USB DFU Interface...
Setting Alternate Setting #0 ...
Determining device status: state = dfuIDLE, status = 0
dfuIDLE, continuing
DFU mode device DFU version 0101
Device returned transfer size 4096
Copying data from PC to DFU device
Download        [=========================] 100%       136164 bytes
Download done.
state(7) = dfuMANIFEST, status(0) = No error condition is present
state(8) = dfuMANIFEST-WAIT-RESET, status(0) = No error condition is present
Done!
Mine showed up as COM8 and For more details on how a RISC-V soft CPU runs MicroPython, see the Fomu as a CPU section of the fomu workshop.

I've been following along with the development of picosoc for the ULX3S. This is included in the full toolchain build, or can be fetched from here:

cd $WORKSPACE
git clone https://github.com/rxrbln/picorv32.git
To build:

# use the rxrbln firmwware
cd $WORKSPACE/rxrbln-picorv32/picosoc

# there have been some recent additions to the source code; some files not included in the repo
# so get an older, know-to-compile version:
git checkout b1cd395b

make ulx3s_fw.img
$WORKSPACE/ulx3s-examples/bin/ujprog.exe -j FLASH -f 0x200000 ulx3s_fw.img

Use the LiteX CPU
# make the soft CPU
cd $WORKSPACE/litex-boards/litex_boards/targets
./ulx3s.py --device LFE5U-85F --cpu-type picorv32

# show the files built
echo "ULX3S Gateware:"
ls $WORKSPACE/litex-boards/litex_boards/targets/soc_basesoc_ulx3s/gateware -al

echo "ULX3S BIOSL"
ls $WORKSPACE/litex-boards/litex_boards/targets/soc_basesoc_ulx3s/software/bios -al

# put the soft CPU on the ULX3S
cd $WORKSPACE/litex-boards/litex_boards/targets/soc_basesoc_ulx3s/gateware
$WORKSPACE/ulx3s-examples/bin/ujprog.exe top.bit

cd $WORKSPACE/litex-boards/litex_boards/targets/soc_basesoc_ulx3s/software/bios
litex_term --serial-boot --kernel bios.bin /dev/ttyS15

Press enter, and you should see a litex> prompt. Type reboot As a reminder, if you keep getting an error like this:

ULX2S / ULX3S JTAG programmer v 3.0.92 (built Feb 18 2019 10:55:47)
FT_Open() failed
Cannot find JTAG cable.
Check to make sure NOTHING is using the ULX3S, including perhaps a litex_term or putty session. (yes, I've bumped into that more than once).

A big Thank You to @GregDavill  for these tips on the twitter thread:

The LiteX bios is what you're seeing running.  
By default, LiteX builds this to execute from address 0x00000000. This is an address space inside the FPGA, using blockram. Litex embeds the code inside so it's baked into the bit-stream. 
uart_sync() just waits until internal uart FIFOs are cleared. (Which ensures that printf data  has been sent to the PC...) printf also relies on interrupts, so once you've disable interrupts printf no longer works.

The bios exists to initialise things like SDRAM, which you can see it doing here. It then tries to load a USER program from SD/FLASH/Serial/Ethernet.

According to the timvideos "what is litex" the flterm program is what is needed to interact with the bios. As of the date of this blog, I've included that in the full ULX3S toolchain install.

Beware there's an old implementation of traps on riscv32 that may cause code crashes. (e.g. soft debugging)

I found an example using flterm: This next section is an unsuccessful attempt to upload firmware with flterm. (it just sits there waiting for something)

cd $WORKSPACE/flterm
./flterm --port /dev/ttyS15 --kernel $WORKSPACE/rxrbln-picorv32/firmware/firmware.bin --kernel-adr 0x40000000

Searching for the term "liftoff" and I found two occurrences here and here:
# remote.origin.url=https://github.com/enjoy-digital/litex

# this is the one that gets compiled:
C:\workspace\litex\litex\soc\software\bios\boot.c

# plus this older file:
C:\workspace\litex-buildenv\third_party\litex\litex\soc\software\bios\boot.c


I created a soft_cpu.sh script soon to be pushed to the ulx3s-toolchain setup to illustrate how I created a picorv32 soft CPU on the ULX3S using LiteX. See my next blog on updating the firmware.

Thursday, March 26, 2020

ESP32-S2 Arrival Day! WSL test drive


My ESP32-S2 Saola R1 arrived!!



What exactly is that? Well, I wondered the same thing. Per the Espressif Products Ordering Information (see page 21)


That means "ESP32-S2 general purpose development board, embeds ESP32-S2-WROVER, 4 MB flash, with pin header".  The "R" means it includes 2MB of PSRAM, (as opposed to the "M" that does not)... and the fact that it is an "R" and not an "RI" means my antenna is the "internal PCB onboard antenna" (as opposed to the "External IPEX antenna".

When mine starts up, it gives some basic info:



Make thanks to @unexpectedmaker for posting an informative video on the ESP32-S2 toolchain setup, including this tip on OTG pins:

ESP32-S2 USB OTG Pins   credit: @unexpectedmaker
I've adapted those notes to run my idf in WSL. There are some dependencies:

sudo apt-get install git wget flex bison gperf python python-pip python-setuptools cmake ninja-build ccache libffi-dev libssl-dev
sudo apt-get install python3 python3-pip python3-setuptools

# system-wide update to default to python3
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 10

See also the install documentation.

I also have this ESP32 install as part of my full ULX3S toolchain installer. (see upstream repo)

Thank you @i_grr for this:
One more thing, do export ESPPORT=/dev/ttyS16 once in the console session, and never have to pass -p argument to idf.py
# copy hello world
cp -r $IDF_PATH/examples/get-started/hello_world esp32-S2_hello_world

cd esp32-S2_hello_world
idf.py set-target esp32s2
idf.py menuconfig
Apparently the menuconfig will assign settings only to this project (again, thank you @unexpectedmaker for the informative video!)

To build:

idf.py build

To flash:

idf.py -p /dev/ttyS16 -b 921600 flash

To monitor (the command-line equivalent of putty):

idf.py -p /dev/ttyS16 -b monitor

Ctrl-[ to cancel

See An Introduction to Modern CMake

more to come...

Saturday, March 14, 2020

RISC-V on the ULX3S with LiteX

Today is ULX3S Campaign Launch Day on Crowd Supply!!

As I write this, funding is at 40% in just the first hour!

In pursuit of my ongoing quest to get Circuit Python working on my ULX3S.... I decided to try out LiteX. I wasn't able to get the rxrbln picorv32 picosoc for ULX3S working (yet) due to some missing files that have not yet been checked in. Part of the journey is simply figuring out which working components to use.

LiteX is included in my full toolchain build for the ULX3S (see my prior blog).

Full ULX3S toolchain directory list
Once everything is installed (OMG, it takes the better part of a day)... we can get started.

First: if you are considering getting your own ULX3S from the upcoming Crowd Supply campaign, be aware that only the larger 45F and 85F versions are available options (and capable?) of running the LiteX VexRiscv.

Some key terminology from timvideos to get started: Gateware (as in Field Programmable Gate Array) is the stuff that gets loaded onto the FPGA. Firmware is the application code that the soft CPU will execute. The BIOS is bootstrapping code baked into FPGA.

Note that I installed my development toolchain on WSL Ubuntu. I've also tested the install multiple times on VM's with real Ubuntu. But here, my blog is about using WSL, so all of my stuff is installed on my local C:\workspace directory, or from WSL's perspective: /mnt/c/workpace. On a real Ubuntu machine, simply replace that with your own ~/workspace/ directory.

Why didn't I just put my workspace in the WSL ~/workspace directory instead? Well for one, I can completely wipe out WSL and reinstall, and all my Windows workspace files are still there. I can also access those files easily from Windows and Visual Studio in particular. I'm still waiting on WSL2 (only available to Windows insider / preview at this time, which I chose not to sign up for) - and I believe I need to rip & replace for that version.

LiteX is a code generator. Not only does it create Verilog, but also a bash script to run yosys / nextpnr / ecppack to actually generate an ECP5 FPGA bit file. The fact that it can generate code to build a complete soft CPU is frankly astonishing.

Run the ulx3s.py for the respective device:
cd /mnt/c/workspace/litex-boards/litex_boards/targets
# ./ulx3s.py --device LFE5U-45F
./ulx3s.py --device LFE5U-85F
It is not super intuitive where files end up. There's certainly not a lot of documentation for the litex-boards repo. I searched in powershell:
Get-ChildItem -Recurse | Where-Object { $_.LastWriteTime -ge "03/08/2020 4:00pm" }
the top.bit file ended up in:
C:\workspace\litex-boards\litex_boards\targets\soc_basesoc_ulx3s\gateware
So from WSL it can be loaded onto the ULX3S like this:
# make sure nothing is using the ULX3S, including VM's, terminal sessions in putty, etc!
cd /mnt/c/workspace/litex-boards/litex_boards/targets/soc_basesoc_ulx3s/gateware

/mnt/c/workspace/ulx3s-examples/bin/ujprog.exe top.bit
Note how Windows executables can be called from the WSL prompt. The same command can be used in a DOS window:
# make sure nothing is using the ULX3S, including VM's, terminal sessions in putty, etc!
c:
cd \workspace\litex-boards\litex_boards\targets\soc_basesoc_ulx3s\gateware

c:\workspace\ulx3s-examples\bin\ujprog.exe top.bit
Stupid things to be aware of: the serial port is running at 11500 8N1. Don't ask me how much time I wasted when using a putty saved connection for the COM port preset at 19200 and kept wondering why there was no response when trying to connect. I don't think I'll ever make that mistake again. lol

There's also an interesting bios.bin file in
C:\workspace\litex-boards\litex_boards\targets\soc_basesoc_ulx3s\software\bios
My script for synthesizing the CPU ended up in:
/mnt/c/workspace/linux-on-litex-vexriscv/build/ulx3s/gateware/build_top.sh
I had found that build_top.sh file prior to realizing ulx3s.py accepted a device parameter. I  have two ULX3S devices, the 12F and the 85F. Guess which one is the defined default for the LiteX build? Yup, the 45F. Did I mention if things are too easy it's no fun? At first I manually edited the build file (note the above call to ulx3s.py does everything, including synthesizing the FPGA VexRiscv core). The default looks like this:
# Autogenerated by LiteX / git: e801dc02
set -e
yosys -l top.rpt top.ys
nextpnr-ecp5 --json top.json --lpf top.lpf --textcfg top.config --45k --package CABGA381 --speed 6 --timing-allow-fail
ecppack top.config --svf top.svf --bit top.bit
Ok, so one of the parameters looks easy enough. Ooph, but what about the "CABGA381"? Well, a quick google search and it turns out that's just a package specification. See the prjtrellis devices.json for a list of all of them. I'll assume that I each of the ECP5 options on the ULX3S will use the same package, and simply change the "45k" to "85k".

There are some bios docs.

Constraint (pin-level) implementation details can be found in platforms/ulx3s.py.

As shown in the ulx3s.py platform file, there's no Ethernet port configured and the serial port is configured for ECP5 pins L4 and M1:

    ("serial", 0,
        Subsignal("tx", Pins("L4"), IOStandard("LVCMOS33")),
        Subsignal("rx", Pins("M1"), IOStandard("LVCMOS33"))
    ),
To build the binaries:

cd $WORKSPACE/litex-boards/litex_boards/targets

./ulx3s.py --device LFE5U-85F --cpu-type picorv32

cd $WORKSPACE/litex-boards/litex_boards/targets/soc_basesoc_ulx3s/gateware

# to program the FPGA as a CPU:
$WORKSPACE/ulx3s-examples/bin/ujprog.exe top.bit

cd /mnt/c/workspace/litex-boards/litex_boards/targets/soc_basesoc_ulx3s/software/bios

litex_term --serial-boot --kernel bios.bin /dev/ttyS15

More to come... see my next blog: ULX3S RISC-V with LiteX - Part 2.


Sunday, March 8, 2020

RISC-V Circuit Python on ULX3S starting with the Hacker FOMU as an example

Some notes on setting up a soft RISC-V CPU to run Circuit Python.

I started with the ambitious idea of wanting Circuit Python to work on the Radiona ULX3S. Easily said...

Really short TL;DR this ended up being mostly a blog about the (mysteries and difficulties of installing) toolchain. See this to get started.

TL;DR; Circuit Python is a "C" app that needs a CPU to run on. The Feather M0 is an ARM processor option known to work well with Circuit Python.  We'll need to configure the ECP5 FPGA to be a soft CPU on the ULX3S, as Circuit Python no longer supports the current ESP32 as of version 4, but the ESP32-S2 will be supportedFomu is an FPGA that's had some work towards Circuit Python. There are multiple Fomu versions. Need to first install foboot. Then the rxrbln fork of Claire Wolf's RISC-V toolchain for the ULX3S ECP5. Note make -j$(nproc) build-tools installs all 4 toolchains, when we probably only want riscv32i. There's an open Adafruit issue regarding Fomu port of CircuitPython #2604. Be careful using a hub. Install FPGA toolchain; see this gist and this repo. Note that 4GB is now the minimum RAM to build prjtrellis, 5GB to build nextpnr-ecp5, and at least 30GB disk.

First, I'd like to extend my thanks to Tim "mithro" Ansell for giving me a pair of Hacker Fomu's at Hackaday 2019. I'm so glad I had a chance to meet him. What an awesome guy!

Many of my notes here are quite similar to my previous, multi-part post on setting up a RISC-V on the tinyFPGA-BX.  See also Luke's picosoc example code here.

There are multiple FOMU versions. My FOMU that I received from Tim looks like this and is the hacker version, using the bash command export FOMU_REV=hacker:



The Adafruit FOMU (#4332) is the production version:


I started following along the timvideos getting started but didn't have a lot of success.

The tutorial references and links to foboot 1.8.1 (evt-installable.dfu) I eventually noticed in the list of releases and a note that the Hacker version did not have support until Version 1.8.8. Of course it didn't. No fun if it's too easy. :)



I also ordered an even more robust, known-good CircuitPython board, the Adafruit Feather M0 Express. This started me down yet another rabbit hole (specifically this) as the fomu didn't play well when sharing a USB hub.

Also - in my case, for some reason the Ubuntu VM no longer had an IP address after rebooting the host. Apparently others have had the same problem. Indeed I needed to add this to my /etc/network/interfaces after confirming ens33 was the name of my network adapter with the ip address command. Nothing is ever as easy as it is supposed to be. The fun never stops! ;)


# The primary network interface
auto ens33
iface ens33 inet dhcp
confirm that ens33 is the proper device.

Update: it seems that Ubuntu only "forgets" the IP address assignment if the VM is paused. During reboots or initial install - the network interface works properly with no edits to the interface file.

Oh - and more that the default 20GB disk space is needed (40GB is safe, but perhaps as little as 35GB) if doing this in a VM. Ubuntu does not automatically recognize a bigger disk after it has been expanded, so gparted needs to be installed as explained on stackexchange. Simply right-click and select "Resize/Move". Be sure to click on the little green check mark to apply changes.


cd ~

# does dfu-util work?
dfu-util -l

# if "Cannot open DFU device 1209:5bf0" try sudo
sudo dfu-util -l

# can't find dfu-util with sudo?
whereis dfu-util

# here we go
sudo /home/gojimmypi/ecp5-toolchain-linux_x86_64-v1.6.2/bin/dfu-util -l

# upgrade foumu
cd workspace
mkdir fomu
cd fomu
wget https://github.com/im-tomu/foboot/raw/master/releases/v1.8.1/evt-installable.dfu
sudo /home/gojimmypi/ecp5-toolchain-linux_x86_64-v1.6.2/bin/dfu-util -D evt-installable.dfu

If successful, should give output like this:

dfu-util 0.9

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2019 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

Match vendor ID from file: 1209
Match product ID from file: 5bf0
Opening DFU capable USB device...
ID 1209:5bf0
Run-time device DFU version 0101
Claiming USB DFU Interface...
Setting Alternate Setting #0 ...
Determining device status: state = dfuIDLE, status = 0
dfuIDLE, continuing
DFU mode device DFU version 0101
Device returned transfer size 1024
Copying data from PC to DFU device
Download [=========================] 100%       106814 bytes
Download done.
state(7) = dfuMANIFEST, status(0) = No error condition is present
state(8) = dfuMANIFEST-WAIT-RESET, status(0) = No error condition is present
Done!

To more gracefully setup permissions see the fomu docs. Basically:
# add this line to /etc/udev/rules.d/99-fomu.rules
SUBSYSTEM=="usb", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="5bf0", MODE="0664", GROUP="plugdev"

And then:

sudo groupadd plugdev
sudo usermod -a -G plugdev $USER
id $USER
sudo udevadm control --reload-rules
sudo udevadm trigger

# logoff then back on


Next, we want to have the rxrbln ULX3S version of PicoRV32:
# on a completely new system:
THISRISCV=riscv32i
THIS_RISCV_PATH=/opt/$THISRISCV/bin
MIN_ULX3S_MEMORY=5050000

if [ $(free | grep Mem | awk '{ print $2 }') -lt $MIN_ULX3S_MEMORY ]; then
  echo ""
  echo "System memory found:"
  free
  echo ""
  read -p "Warning, at least $MIN_ULX3S_MEMORY bytes of memory is needed. Press$
fi


sudo apt-get update --assume-yes 
sudo apt-get upgrade --assume-yes
sudo apt-get install git --assume-yes

cd ~
mkdir -p ~/workspace
cd workspace

git clone https://github.com/rxrbln/picorv32.git

cd picorv32

sudo apt-get install make        --assume-yes
sudo apt-get install make-guile  --assume-yes
sudo apt-get install libgmp3-dev --assume-yes
sudo apt-get install libmpfr-dev --assume-yes
sudo apt-get install libmpc-dev  --assume-yes

sudo apt-get install autoconf automake autotools-dev curl libmpc-dev \
        libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo \
    gperf libtool patchutils bc zlib1g-dev git libexpat1-dev --assume-yes


make download-tools

# install *all four* riscv flavor toolchains:
# make -j$(nproc) build-tools

# or install only riscv32i:
sudo mkdir /opt/riscv32i
sudo chown $USER /opt/riscv32i

git clone https://github.com/riscv/riscv-gnu-toolchain riscv-gnu-toolchain-rv32i
cd riscv-gnu-toolchain-rv32i
git checkout 411d134

# if you see fatal: clone of 'git://  ... 
# users sitting behind a firewall may need these:
git config --global url.https://github.com/.insteadOf git://github.com/
git config --global url.https://git.qemu.org/git/.insteadOf git://git.qemu-project.org/
git config --global url.https://anongit.freedesktop.org/git/.insteadOf git://anongit.freedesktop.org/
git config --global url.https://github.com/riscv.insteadOf git://github.com/riscv

# this next statement takes a long time. be patient:
git submodule update --init --recursive

mkdir build; cd build
../configure --with-arch=rv32i --prefix=/opt/riscv32i
make -j$(nproc)

# see if it is working:
/opt/riscv32i/bin/riscv32-unknown-elf-gcc --version

# add to path
if [ "$(cat ~/.bashrc | grep  $THIS_RISCV_PATH)" == "" ]; then
  echo PATH=$PATH:$THIS_RISCV_PATH >> ~/.bashrc
  echo "~/.bashrc updated with this line:"
  echo PATH=$PATH:$THIS_RISCV_PATH
else
  echo "Found $THIS_RISCV_PATH in ~/.bashrc - path not changed."
fi

if [ "$(echo $PATH | grep  $THIS_RISCV_PATH)" == "" ]; then
  export PATH=$PATH:$THIS_RISCV_PATH
  echo "Updated current path: $PATH"
else
  echo "Path not updated. PATH=$PATH"
fi

cd ~/workspace
git clone https://gist.github.com/gojimmypi/f96cd86b2b8595b4cf3be4baf493c5a7 ulx3s_fpga_toolchain
cd ulx3s_fpga_toolchain
chmod +x ULX3S_WSL_Toolchain.sh
./ULX3S_WSL_Toolchain.sh



Run scripts with the source command if you don't want to start a new shell, or manually set path. You may wish to put this line at the end of your ~/.bashrc file:
#add path to riscv32i compiler
PATH=/opt/riscv32i/bin:$PATH

Once the RISC-V toolchain is installed, there's some sample code in the picosoc directory. Fortunately rxrbln has already made some modifications in the Makefile for the ULX3S. The C code is compiled with:

make ulx3s_fw.img


To upload the code to the ULX3S:

make ulx3sprog


Note from the Makefile there are 2 key steps: #1 to put the ulx3s.bit soft CPU onto the FPGA, then #2 put the firmware into FLASH memory:
/usr/src/f32c-ujprog/ujprog/ujprog -j FLASH -f 0x200000 ulx3s_fw.img
/usr/src/f32c-ujprog/ujprog/ujprog -t ulx3s.bit # -j FLASH 


The default install directory for ujprog is /usr/local/bin/ujprog however the rxrbln Makefile expects it to be /usr/src/f32c-ujprog/ujprog/ujprog
so we'll just create a quick symlink
sudo mkdir -p /usr/src/f32c-ujprog/ujprog/
sudo ln -s /usr/local/bin/ujprog /usr/src/f32c-ujprog/ujprog/ujprog
yosys/nextpnr/ https://gist.github.com/gojimmypi/243fc3a6eead72ae3db8fd32f2567c96


In the end, I put together a full ULX3S toolchain installer. Next blog I go into details of actually getting the soft CPU and RISC-V code onto the ULX3S.


Other stuff:

TODO - do we really want a 2+ year old RV32I toolchain? (note git checkout 411d134)



 * https://workshop.fomu.im/en/latest/

See also:

A cobbled-together profiler for CircuitPython.

Find gojimmypi at gojimmypi.github.io

I'm currently working on my new blog home at  gojimmypi.github.io After implementing a variety of features such as dark mode , syntax hi...