Showing posts with label ULX3S. Show all posts
Showing posts with label ULX3S. Show all posts

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 ECP5. LiteX 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.

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 supported. Fomu 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.

Tuesday, December 24, 2019

ULX3S and IceStudio

Today I learned that IceStudio supports the ULX3S! I thought I'd first try it in WSL Ubuntu.

I'm not sure if X-Windows server is needed, but I have some notes in a prior blog post to use cygwin from WSL.

sudo apt-get update  
sudo apt-get upgrade 
sudo apt-get install nodejs
sudo apt-get install npm
node -v
cd ~/workspace/

## see https://github.com/FPGAwars/icestudio#download
##
git clone https://github.com/FPGAwars/icestudio.git
cd icestudio

## Do we need to have an X-Windows server running?
##
export DISPLAY=:0 # you may wish you put in this your ~/.bashrc
cp /mnt/c/cygwin64/home/gojimmypi/.Xauthority   ~/.Xauthority

## test X-Windows
xclock

## ensure we are on the develop branch
##
git status 

npm install
npm start

Unforunately, this left me in a state of "waiting..."



gojimmypi:~/workspace/icestudio
$ npm start

> icestudio@0.5.1 start /home/gojimmypi/workspace/icestudio
> grunt serve

Running "nggettext_compile:all" (nggettext_compile) task

Running "watch:scripts" (watch) task
Waiting...
Running "wiredep:task" (wiredep) task

Running "exec:stopNW" (exec) task

Running "exec:nw" (exec) task

Done.
Completed in 3.118s at Tue Dec 24 2019 06:57:33 GMT-0800 (PST) - Waiting...


For Windows, download the NodeJS and NPM. I did get it working, but see this icestudio GitHub issue #368. More to come...

Resources and links:

Saturday, June 1, 2019

ULX3S and Visual Micro in Visual Studio 2019

This blog is a walk-though using the Visual Micro Arduino IDE in Visual Studio 2019 to program the ESP32 on the Radiona ULX3S. For more information on the ULX3S see my Day 1 intro, Using ujprog on WSL or MinGW, and Notes on ulx3s FPGA: Yosys, Verilog, VHDL, vhdl2vl (Convert VHDL to Verilog). Here's the ULX3S with the SPIDriver.

ULX3S with SPIDriver board
There are some brief online instructions for manually installing Visual Micro, or you can follow along here, using the VisualMicro example for the ULX3Son GitHub:

In Visual Studio 2019, click on Extensions - Manage Extensions.


Select "online" in the left pane and type "Arduino" in the search box:


Note the 5 stars reviews from hundreds of users. Yes, it is a very cool extension. :)

Next, click on the "Download" button. You'll need to restart Visual Studio 2019.

Be sure to wait for the VSIX installer screen! The first time I did this, I simply launched Visual Studio right away, and the Visual Micro Extension was no where to be found! Before launching Visual Studio, you should see this screen:


Then after a warning about system changes, this prompt:


Click the "Modify" button to continue. Upon completion, there should be a message "Modifications Complete"


When Visual Studio is next launched, click on "Create a new project"


There are many project types, so type "Arduino" in the search box:


Select "Arduino Project" and click the Next button.


Give the project a name, and a location to store it. In this case, I am saving it in my ULX3S examples fork directory, to create a pull request to the official ULX3S Examples.

After clicking  the "Create" button, a familiar Arduino-style code template is created, with the setup() and loop() functions:


So that's the easy part. Now things get more interesting. The ESP32 on the ULX3S sits behind the FPGA chip. This means the only way to program the ESP32, is to have code on the ULX3S that performs a "pass through" function of external physical pins to the ESP32 pins through the FPGA.

schematic showing the ESP32 to FPGA connections


Fortunately, the ULX3S typically ships with the pass-though FPGA app already loaded. If not, the FPGA source code can be found here. Note there are three different versions: the Diamond VHDL that emard wrote, a Diamond Verilog that I converted from emard's VHDL, and finally an Open Source Verilog version that uses yosys and nextpnr. (hm, it looks like from the most recent comments I need to get the open source version working properly - I'll need to look into that)

If you are not ready to jump into the synthesis of FPGA bit files yet, you can use the passthru image file passthru_ulx3s_v20_12k.bit and load it onto the ESP32 using the ujprog tool. If you don't feel like building your own, there's a copy of both the bin directory.


if NOT EXIST c:\workspace mkdir c:\workspace
git clone https://github.com/gojimmypi/ulx3s-examples.git c:\workspace\ulx3s-examples
c:
cd \workspace\ulx3s-examples\VisualMicro\bin\
.\ujprog.exe passthru.bit


If "Cannot find JTAG cable" is encountered, remember that WSL is still not supporting native USB drivers. If you are using the Windows executable version and you see that message try changing the ULX3S drivers back to FTDI particularly if you don't see your ULX3S in the Ports (COM & LPT) container in device manager. WSL can be finicky, and even have different results whether executing from a Linux directory or DOS (e.g. /mnt/c/). And yes, native Windows executable files can be launched from WSL! cool.

Visual Studio seemed to have defaulted to all the correct values for me (I'm note sure if perhaps it remembered values from Visual Studio 2017) Here they are for reference:


Of particular interest is ensuring the proper COM port is selected, near the bottom of the settings list. I didn't see the actual ESP32 device listed (WROOM-32), so I used the ESP32 Dev Module setting.

Once the pass through FPGA binary has been successfully uploaded, the simplest way to compile and upload the Arduino code via Visual Micro is to press F5 or the big green "start" button! That's it!

Note that one of the amazing things about the Visual Micro IDE, is they have implemented a debugger that does not require a hardware JTAG device! Here's my ULX3S ESP32 paused at a breakpoint:


Now onto that SPI Driver! Stay tuned for more....





Sunday, March 31, 2019

ULX3S SDR with ALINX AD/DA

Last year, I wrote about the ALINX AD/DA Module that I found on fleabay. Anyone interested in this board should certainly watch the video posted by opentechlab.

Key tidbits of information from the video:

  • DAC is powered by onboard 3.3V regulator.


  • Output from the DAC is differential 3vpp; (true output is difference) each output goes though a low pass filter for anti-aliasing. 


  • Fed into AD 8056 op-amp to convert differential signal to single-ended and level shift from 3vpp to 10vpp (-5 to +5V)


  • Potentiometer is used to control gain of output.


  • There's a bit of input protection on the ADC.


  • Input filter converts 10vpp to 3vpp for ADC chip.


  • MC34063 Step-Up/Down/Inverting Switching Regulators to generate negative rail for output from single +5VDC supply.



Links:

Sunday, February 17, 2019

Notes on ulx3s FPGA: Yosys, Verilog, VHDL, vhdl2vl (Convert VHDL to Verilog)

I want to better understand my new ULX3S, and I was hoping to use FOSS FPGA tools. Here I document some things I've recently learned:

Some key points (from https://gitter.im/ulx3s/Lobby/ ):
  • the standard JTAG programming stuff only programs FPGA SRAM; So rebooting the board will "recover" it 
  • In general you have to go through a fairly tedious process involving Diamond Deployment Tool to create a SVF file to program flash, and this will be very slow Otherwise, you are just programming SRAM (update: this is no longer the case; see ujprog -j flash file.bit
-- @daveshah1
and:
  • I guess the ulx3s-passthru bitstream is by default shipped to you, when you have OLED and ESP32 in box then it makes sense to load the board with passthru.
  • Other boards without OLED and/or ESP32 are probably shipped with f32c with FAT filesystem on config flash to run self-test application at power up.
  • You can erase config flash and ESP32 with whatever you want and flash back to "factory default" from my ulx3s-bin repository.
  • passthru is old source and it needs updated makefile like in prjtrellis-dvi. Yes it tries to find diamond.
  • Passthru is very simple and it could be ported done using opensource tools only. I'm using vhd2vl. For most simple vhdl examples it works great.
  • It can't convert if VHDL source is complex/advanced and has functions and packages.
-- @emard
I case you are wondering about that second USB port (the left one, when facing them):
don't touch the second USB port - it's wired directly into FPGA and thus won't even enumerate on the PC as a serial port unless you do some serious coding at FPGA side (see TinyFPGA Bootloader project - it's pretty much all about it) ... instead, use USB1 which is wired through FT231 chip (see info here)
-- @reostat 
My favorite claims / features:
  • ULX3S is unbrickable. 
-- @emard
and:
  • There is no realistic chance of irreparable damage to the ULX3S in any case
-- @daveshah1

The term "iCEStorm Toolchain" does not mean Yosys, arache-pnr, nextpnr, Trellis; just iCEStorm.

Yosys, arache-pnr, nextpnr, Trellis supports only Verilog, not VHDL

I have a ULX3S 12K. The Blinky from DoctorWkt expects a 45F chip. Even when editing the original Makefile to instead use the --12 option, nextpnr-ecp5 failed:
Yosys 0.8+148 (git sha1 e112d2fb, clang 6.0.0-1ubuntu2 -fPIC -Os)
Time spent: 54% 11x read_verilog (0 sec), 9% 6x techmap (0 sec), ...
nextpnr-ecp5 --12k --json blinky.json --basecfg ulx3s_empty.config \
--lpf ulx3s_v20.lpf \
--textcfg ulx3s_out.config
unrecognised option '--12k'
Makefile:74: recipe for target 'ulx3s_out.config' failed
make: * [ulx3s_out.config] Error 255
In fact, things were looking pretty bleak, as the nextpnr-ecp5 does not even list the 12F:
nextpnr-ecp5 -- Next Generation Place and Route (git sha1 4c73061)

General options:
  -h [ --help ]             show help
  -v [ --verbose ]          verbose output
  -q [ --quiet ]            quiet mode, only errors and warnings displayed
  -l [ --log ] arg          log file, all log messages are written to this file
                            regardless of -q
  --debug                   debug output
  -f [ --force ]            keep running after errors
  --gui                     start gui
  --run arg                 python file to execute instead of default flow
  --pre-pack arg            python file to run before packing
  --pre-place arg           python file to run before placement
  --pre-route arg           python file to run before routing
  --post-route arg          python file to run after routing
  --json arg                JSON design file to ingest
  --seed arg                seed value for random number generator
  -r [ --randomize-seed ]   randomize seed value for random number generator
  --slack_redist_iter arg   number of iterations between slack redistribution
  --cstrweight arg          placer weighting for relative constraint
                            satisfaction
  --pack-only               pack design only without placement or routing
  --ignore-loops            ignore combinational loops in timing analysis
  -V [ --version ]          show version
  --test                    check architecture database integrity
  --freq arg                set target frequency for design in MHz
  --no-tmdriv               disable timing-driven placement
  --save arg                project file to write
  --load arg                project file to read

Architecture specific options:
  --25k                     set device type to LFE5U-25F
  --45k                     set device type to LFE5U-45F
  --85k                     set device type to LFE5U-85F
  --um-25k                  set device type to LFE5UM-25F
  --um-45k                  set device type to LFE5UM-45F
  --um-85k                  set device type to LFE5UM-85F
  --um5g-25k                set device type to LFE5UM5G-25F
  --um5g-45k                set device type to LFE5UM5G-45F
  --um5g-85k                set device type to LFE5UM5G-85F
  --package arg             select device package (defaults to CABGA381)
  --speed arg               select device speedgrade (6, 7 or 8)
  --basecfg arg             base chip configuration in Trellis text format
                            (deprecated)
  --override-basecfg arg    base chip configuration in Trellis text format
  --textcfg arg             textual configuration in Trellis format to write
  --lpf arg                 LPF pin constraint file(s)
@daveshah1 to the rescue once again!
pass --25k to nextpnr, remove the basecfg if your nextpnr is yesterday or today's build otherwise point it to a 25k basecfg, and then pass --idcode 0x21111043 to ecppack
-- @daveshah1

I'm not sure I would have ever guessed the 25F, and certainly not the --idcode 0x21111043 part. I pulled the latest SymbiFlow/prjtrellis and nextpnr now (git sha1 4c73061), cleaned and rebuilt everything with my new Makefile, and success to build!
[... snip ..]
Info: [ 79471,  79958) |
Info: [ 79958,  80445) |***
Info: [ 80445,  80932) |*
Info: [ 80932,  81419) |***
Info: [ 81419,  81906) |********
337 warnings, 0 errors
ecppack ulx3s_out.config ulx3s.bit --idcode 0x21111043
Now recall I am doing this all in WSL Ubuntu, so there are no native USB devices - thus I am forced to use the Windows version of ujprog to actually upload the code to the ULX3S board.

The amazing thing here - is that Windows applications can be run from within WSL!

This seems to completely circumvent the "No Native USB Devices" in WSL. For example, here's the same app compiled for linux, not finding the JTAG device:



I'm using the very latest FTDI code in my fork of the f32c tools (I created this PR #9). I still encountered some problems with the syntax of the ujprog. I opened issue #10, which was promptly closed - regarding the expected operation. Bottom line is this is the syntax that works:
C:\workspace-git\f32c_tools\ujprog>ujprog ulx3s.bit
ULX2S / ULX3S JTAG programmer v 3.0.92 (built Feb 13 2019 12:27:20)
Using USB cable: ULX3S FPGA 12K v3.0.3
Programming: 100%
Completed in 18.66 seconds.
And I learned a few more things in the close comment:
JTAG doesn't work in COM mode, so no wonder that uploading a bitstream can't work that way, especially not when using the -a modifier, which tells the ujprog to send the file as a stream of bytes.
-- gornjas
From gitter:
ujprog note: supported targets are either -j sram or -j flash
-- @emard
So, ya - I get that all this stuff is obvious to the developers & subject matter experts; However, I struggled to learn each of these things when seeing it all for the first time and relatively little documentation. Although there's no README in the f32c/tools/ujprog, I created one in my fork that hopefully will help others.

As mentioned above: in order to program the ESP32, the FPGA needs to be configured in "Pass-Through" mode. @emard's ulx3s-passthru is written in VHDL.

There's a tool called vhdl2vl that can convert some VHDL to Verilog. Yosys has a VDHL reader plugin based on vhdl2vl.
git clone https://github.com/YosysHQ/yosys-plugins.git
cd yosys-plugins/vhdl
make

# mkdir -p /usr/local/share/yosys/plugins
# cp vhdl.so /usr/local/share/yosys/plugins/vhdl.so
sudo make install
then run yosys, and from the yosys> prompt:
plugin  -i vhdl
plugin  -l
This will add a new read_vhdl command to yosys.

There is more documentation on yosys here.

If the plugin is listed and working, typing read_vhdl in yosys will show help:
1. Executing VHDL frontend.

Syntax error in command `read_vhdl':

    read_vhdl [options] [filename]

Load modules from a VHDL file to the current design.

    -dump_ast1
        dump abstract syntax tree (before simplification)

    -dump_ast2
        dump abstract syntax tree (after simplification)

    -no_dump_ptr
        do not include hex memory addresses in dump (easier to diff dumps)

    -dump_vhdl
        dump ast as VHDL code (after simplification)

    -yydebug
        enable parser debug output

    -nolatches
        usually latches are synthesized into logic loops
        this option prohibits this and sets the output to 'x'
        in what would be the latches hold condition

        this behavior can also be achieved by setting the
        'nolatches' attribute on the respective module or
        always block.

    -nomem2reg
        under certain conditions memories are converted to registers
        early during simplification to ensure correct handling of
        complex corner cases. this option disables this behavior.

        this can also be achieved by setting the 'nomem2reg'
        attribute on the respective module or register.

        This is potentially dangerous. Usually the front-end has good
        reasons for converting an array to a list of registers.
        Prohibiting this step will likely result in incorrect synthesis
        results.

    -mem2reg
        always convert memories to registers. this can also be
        achieved by setting the 'mem2reg' attribute on the respective
        module or register.

    -nomeminit
        do not infer $meminit cells and instead convert initialized
        memories to registers directly in the front-end.

    -ppdump
        dump VHDL code after pre-processor

    -nopp
        do not run the pre-processor

    -nodpi
        disable DPI-C support

    -lib
        only create empty blackbox modules. This implies -DBLACKBOX.

    -noopt
        don't perform basic optimizations (such as const folding) in the
        high-level front-end.

    -icells
        interpret cell types starting with '$' as internal cell types

    -nooverwrite
        ignore re-definitions of modules. (the default behavior is to
        create an error message if the existing module is not a black box
        module, and overwrite the existing module otherwise.)

    -overwrite
        overwrite existing modules with the same name

    -defer
        only read the abstract syntax tree and defer actual compilation
        to a later 'hierarchy' command. Useful in cases where the default
        parameters of modules yield invalid or not synthesizable code.

    -noautowire
        make the default of `default_nettype be "none" instead of "wire".

    -setattr <attribute_name>
        set the specified attribute (to the value 1) on all loaded modules

    -Dname[=definition]
        define the preprocessor symbol 'name' and set its optional value
        'definition'

    -Idir
        add 'dir' to the directories which are used when searching include
        files

The command 'vhdl_defaults' can be used to register default options for
subsequent calls to 'read_vhdl'.

Note that the VHDL frontend does a pretty good job of processing valid
VHDL input, but has not very good error reporting. It generally is
recommended to use a simulator for checking the syntax of the code, rather
than to rely on read_vhdl for that.
The yosys VHDL plugin reads a VDHL file like this:
yosys> read_vhdl ulx3s_v20_passthru_wifi.vhd

3. Executing VHDL frontend.
Parsing VHDL input from `ulx3s_v20_passthru_wifi.vhd' to AST representation.
ERROR: NOT IMPLEMENTED: ulx3s_v20_passthru_wifi.vhd:16 (vhdl_parser.y:1583)
There is probably a different message if it was successful.

There's also the vhd2vl noted on the yosys README.
git clone https://github.com/ldoolitt/vhd2vl.git
cd vhd2vl/src
make
./vhd2vl ../../ulx3s-passthru/rtl/ulx3s_v20_passthru_wifi.vhd
With a bit of help info:
./vhd2vl --help
Usage: vhd2vl [--debug] [--quiet] [--std 1995|2001] source_file.vhd > target_file.v
   or  vhd2vl [--debug] [--quiet] [--std 1995|2001] source_file.vhd target_file.v
That also had limited success:

// File ../../ulx3s-passthru/rtl/ulx3s_v20_passthru_wifi.vhd translated with vhd2vl v3.0 VHDL to Verilog RTL translator
// vhd2vl settings:
//  * Verilog Module Declaration Style: 2001

// vhd2vl is Free (libre) Software:
//   Copyright (C) 2001 Vincenzo Liguori - Ocean Logic Pty Ltd
//     http://www.ocean-logic.com
//   Modifications Copyright (C) 2006 Mark Gonzales - PMC Sierra Inc
//   Modifications (C) 2010 Shankar Giri
//   Modifications Copyright (C) 2002-2017 Larry Doolittle
//     http://doolittle.icarus.com/~larry/vhd2vl/
//   Modifications (C) 2017 Rodrigo A. Melo
//
//   vhd2vl comes with ABSOLUTELY NO WARRANTY.  Always check the resulting
//   Verilog for correctness, ideally with a formal verification tool.
//
//   You are welcome to redistribute vhd2vl under certain conditions.
//   See the license (GPLv2) file included with the source for details.

// The result of translation follows.  Its copyright status should be
// considered unchanged from the original VHDL.

WARNING (line 70): port default initialization ignored.
WARNING (line 70): port default initialization ignored.
WARNING (line 70): port default initialization ignored.
WARNING (line 70): port default initialization ignored.
WARNING (line 70): port default initialization ignored.
syntax error, unexpected GENERATE at "generate" in line 145.

So the reality is that I probably won't be converting VHDL to Verilog anytime soon. However, writing my own Verilog passthrough app should be an excellent beginner FPGA to write.

Tuesday, February 12, 2019

ULX3S - ujprog on Windows WSL or MingGW

I continue to learn about my latest gizmo that arrived all the way from Croatia - the ULXS3. (see my prior blog)

TL;DR; @emard has precompiled binaries. Otherwise compile your own ujprog using apt-get install mingw-w64. A specific makefile is needed to use the new compiler. The current f32c repo has a very old 32-bit ftd2xx.lib; the updated 64 bit version will typically be needed on modern machines. New drivers are here. The ujprog and OpenOCD for ULX3S cannot be used concurrently (FTDI vs libusbK drivers). See the ujprog README that I created.

I've been trying to use WSL for FPGA development. I'm primarily a Windows developer for the Day Job. I like the Windows tools - particularly Visual Studio and VS Code. I also simply think WSL is really cool. (see also WSL on GitHub)

As a reminder, do not modify WSL filesystem file from Windows! Yes, I've seen some pretty weird things happen when I tested that. But feel free to edit any other files. For instance, the entire C:\ directory is available in WSL as /mnt/c/.

Note that similar to the TinyFPGA setup script, I also created a ULXS3 Setup Script.

One of the problems with WSL is the lack of native USB support (glaring omission, I know). So I wanted to see if the ujprog JTAG programmer could be used from Windows. Not super cool having a disjointed environment. For example, when creating the ujprog in WSL:
git clone https://github.com/f32c/tools.git f32c_tools
cp Makefile.linux Makefile
make
./ujprog -t
I see this result:

$ ./ujprog -t
ULX2S / ULX3S JTAG programmer v 3.0.92 (built Feb 12 2019 10:14:16)
Cannot find JTAG cable.

If compiling ujprog for Windows (yes, I admit I tried to type make at a DOS prompt - lol!), install MinGW (I downloaded mine from here; the downloads link however points here). See the wiki: HOWTO Install the MinGW GCC Compiler Suite.


Press "Continue" and upon completion:


Then the MinGW install manager runs:


I chose these options:


Then click "Installation - Apply Changes"


When finished, there should be an indication that "all changes applied successfully"


From Windows, run:

C:\MinGW\msys\1.0\msys.bat


The MINGW32 home directory (from the Windows perspective) will be: C:\MinGW\msys\1.0\home\{your user name}

Unlike other bash prompts, this one does not seem to map the entire C:\ drive, so I re-cloned the repo to my home/workspace directory in MinGW32:

mkdir workspace
cd workspace
git clone https://github.com/f32c/tools.git f32c_tools

Try to compile the linux make file:

cp Makefile.linux Makefile
make

of course results in failure:

$ make
cc -Wall -D__linux__  -static ujprog.c /usr/lib/`uname -m`-linux-gnu/libftdi.a /usr/lib/`uname -m`-linux-gnu/libusb.a -o ujprog
/bin/sh: cc: command not found
make: *** [ujprog] Error 127

Try to compile the win make file (copy the respective Makefile so the -f is not needed every time):

cp Makefile.win Makefile
make

results in a bunch of warnings repeated about usleep, but more importantly a critical error: 'EOPNOTSUPP' undeclared as shown here:

In file included from ujprog.c:55:
[... snip ...]
c:\mingw\include\unistd.h:100:29: note: declared here
 int __cdecl __MINGW_NOTHROW usleep( useconds_t )__MINGW_ATTRIB_DEPRECATED;
                             ^~~~~~
ujprog.c: In function 'shutdown_usb':
ujprog.c:621:2: warning: 'usleep' is deprecated [-Wdeprecated-declarations]
  ms_sleep(10);
  ^~~~~~~~
In file included from ujprog.c:55:
c:\mingw\include\unistd.h:100:29: note: declared here
 int __cdecl __MINGW_NOTHROW usleep( useconds_t )__MINGW_ATTRIB_DEPRECATED;
                             ^~~~~~
ujprog.c: In function 'exec_svf_tokenized':
ujprog.c:1488:9: error: 'EOPNOTSUPP' undeclared (first use in this function); did you mean 'WSAEOPNOTSUPP'?
   res = EOPNOTSUPP;
         ^~~~~~~~~~
         WSAEOPNOTSUPP
ujprog.c:1488:9: note: each undeclared identifier is reported only once for each function it appears in
ujprog.c: In function 'async_read_block':
ujprog.c:2788:4: warning: 'usleep' is deprecated [-Wdeprecated-declarations]
    ms_sleep(backoff * 4);
    ^~~~~~~~
In file included from ujprog.c:55:
[... snip ...]
I tried making the changes described in nmap/nmap#183 - specifically adding to ujprog.c:

#undef EOPNOTSUPP
#define EOPNOTSUPP      WSAEOPNOTSUPP  /* Operation not supported */

And Voila! Success! ujprog.exe for Windows! I created issue this f32c/tools/#8 and this PR f32c/tools#9 to help others that may encounter this problem.

I'm not sure this PR will be accepted, as the root cause may be:
 probably including a wrong errno.h
When running ujprog.exe (from either MinGW32 bash prompt, or DOS command prompt):

ULX2S / ULX3S JTAG programmer v 3.0.92 (built Feb 10 2019 15:25:08)
Usage: ujprog [option(s)] [bitstream_file]

 Valid options:
  -p PORT       Select USB JTAG / UART PORT (default is 0)
  -P COM        Select COM port (valid only with -t or -a)
  -j TARGET     Select bitstream TARGET as SRAM (default) or FLASH (XP2 only)
  -f ADDR       Start writing to SPI flash at ADDR, optional with -j flash
  -s FILE       Convert bitstream to SVF FILE and exit
  -r            Reload FPGA configuration from internal Flash (XP2 only)
  -t            Enter terminal emulation mode after completing JTAG operations
  -b SPEED      Set baudrate to SPEED (300 to 3000000 bauds)
  -e FILE       Send and execute a f32c (MIPS/RISCV) binary FILE
  -x SPEED      Set binary transfer speed, optional with -e
  -a FILE       Send a raw FILE
  -d            debug (verbose)
  -D DELAY      Delay transmission of each byte by DELAY ms
  -q            Suppress messages

This seemed to be a convoluted solution (hm. as always). So a bit of googling and I found a stackoverflow regarding using MinGW for Ubuntu. Something a little more direct from WSL:
sudo apt-get install mingw-w64
It is however, massive, at nearly 750 MB:
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
  binutils-mingw-w64-i686 binutils-mingw-w64-x86-64 g++-mingw-w64 g++-mingw-w64-i686 g++-mingw-w64-x86-64
  gcc-mingw-w64 gcc-mingw-w64-base gcc-mingw-w64-i686 gcc-mingw-w64-x86-64 mingw-w64-common mingw-w64-i686-dev
  mingw-w64-x86-64-dev
Suggested packages:
  gcc-7-locales wine wine64
The following NEW packages will be installed:
  binutils-mingw-w64-i686 binutils-mingw-w64-x86-64 g++-mingw-w64 g++-mingw-w64-i686 g++-mingw-w64-x86-64
  gcc-mingw-w64 gcc-mingw-w64-base gcc-mingw-w64-i686 gcc-mingw-w64-x86-64 mingw-w64 mingw-w64-common
  mingw-w64-i686-dev mingw-w64-x86-64-dev
0 upgraded, 13 newly installed, 0 to remove and 1 not upgraded.
Need to get 127 MB of archives.
After this operation, 744 MB of additional disk space will be used.
So after the install, a quick compile resulted in:
gcc.exe -c ujprog.c -o ujprog.o -I.
make: gcc.exe: Command not found
Makefile:29: recipe for target 'ujprog.o' failed
make: *** [ujprog.o] Error 127
Ah yes, of course. The Makefile needs to be adjusted to use the new mingw compiler (I added to my PR, suggesting to include a new Makefile.ming32_64:
# Project: ujprog

CPP  = x86_64-w64-mingw32-gcc
CC   = x86_64-w64-mingw32-gcc
WINDRES = windres.exe
RES  =
OBJ  = ujprog.o $(RES)
LINKOBJ  = ujprog.o $(RES)
LIBS = -s -static -L. -lftd2xx
INCS = -I.
CXXINCS = -I.
BIN  = ujprog.exe
CXXFLAGS = $(CXXINCS) -wAll
CFLAGS = $(INCS)
RM = rm -f

.PHONY: all all-before all-after clean clean-custom

all: all-before ujprog.exe all-after


clean: clean-custom
        ${RM} $(OBJ) $(BIN)

$(BIN): $(OBJ)
        $(CC) $(LINKOBJ) -lftd2xx -o "ujprog.exe" $(LIBS)

ujprog.o: ujprog.c
        $(CC) -c ujprog.c -o ujprog.o $(CFLAGS)

The next problem was the ftd2xx.lib file was meant for Linux not Windows, 32 bit not 64 bit .

$ make
x86_64-w64-mingw32-gcc -c ujprog.c -o ujprog.o -I.
x86_64-w64-mingw32-gcc ujprog.o  -lftd2xx -o "ujprog.exe" -s -static -L. -lftd2xx
/usr/bin/x86_64-w64-mingw32-ld: skipping incompatible ./ftd2xx.lib when searching for -lftd2xx
/usr/bin/x86_64-w64-mingw32-ld: cannot find -lftd2xx
/usr/bin/x86_64-w64-mingw32-ld: skipping incompatible ./ftd2xx.lib when searching for -lftd2xx
/usr/bin/x86_64-w64-mingw32-ld: cannot find -lftd2xx
collect2: error: ld returned 1 exit status
Makefile:26: recipe for target 'ujprog.exe' failed
make: *** [ujprog.exe] Error 1
Searching my entire drive, I found the Windows DLL version in my C:\downloads\FTDI directory. Specifically from the WSL perspective:
cd ~/workspace/f32c_tools/ujprog
cp '/mnt/c/download/FTDI/CDM v2.12.28 WHQL Certified/amd64/ftd2xx.lib' ./ftd2xx.lib
make clean
make
This successfully compiled the Windows exe, leaving the file in the Windows-equivalent of my Ubuntu directory:
C:\Users\gojimmypi\AppData\Local\Packages\CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc\LocalState\rootfs\home\gojimmypi\workspace\f32c_tools\ujprog
Sadly, I received the same error in Windows as I did in WSL:
ULX2S / ULX3S JTAG programmer v 3.0.92 (built Feb 12 2019 17:48:54)
FT_Open() failed
Cannot find JTAG cable.
I later discovered this problem was a Windows device driver conflict. In my prior blog, I got OpenOCD working. It uses the libusbK drivers. However, ujprog.exe uses the FTDI drivers. Changing the Windows drivers back to FTDI allows the freshly compiled app to work from Windows!

Now on to getting more serious by uploading my own FPGA and ESP32 code. I'll need to be super sure I can get back to "as shipped" FPGA image, otherwise I may not be able to program the ESP32 since it is not connected directly to any of the exposed pins, rather only the FPGA (same with the SPI display). Thus a passthru app is needed:
Yes, if ESP32 needs FPGA as bypass logic to OLED. If you need ESP32 to write to OLED while FPGA is running user defined core then those few OLED bypass signals must be copy pasted from passthru source to user's source. It's makes very small LUT usage.
--@emard
More info coming soon!

Resources, Inspiration, Credits, and Other Links:

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...