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:

No comments:

Post a Comment

comments are welcome, but I prefer not to allow links to promotions or other unrelated services.

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