Unless you know what you're doing, you should test your new UMDK cart using a recent x86 or x64 Linux installation, on "real" (as opposed to virtual, e.g on VMware or VirtualBox) x86 or x64 hardware. The software will build and function correctly on MacOSX or Windows, or even on a Raspberry Pi, but whilst we're getting everyone up and running it makes sense to minimize the number of configurations being used.
So, you will need:
- A PC with a spare USB port and an Internet connection
- A recent Linux installation, x86 or x64 (amd64)
- A digital multimeter, for verifying voltage levels
- Four jumpers, for selecting options on the boards
- A good solid block of time to run through the test and install process
- Patience!
Now we can split into two groups:
- If you built your own UMDK cart, or bought it direct from a manufacturer, you're in group A
- If you bought your UMDK from a member of the SpritesMind community, you're in group B
Got all that? Great! Let's go!
First, make sure sudo
works:
$ sudo ls
[sudo] password for <user>: *********
:
$
If it fails, you'll need to find out how to enable sudo
on your particular Linux distro. Ubuntu normally has it pre-installed; on Debian you'll need to do apt-get install sudo
as root and then add yourself to the sudo
group; on Fedora you'll need to add yourself to the wheel
group. Google is your friend.
Next, if you want to use the DDD debugger front-end, you'll have to install it. Again, this will depend on your OS, but it'll probably be something like sudo apt-get install ddd
or sudo yum install ddd
.
Next, entitlements. Since Linux is a multiuser OS, ordinary users are by default not allowed to access USB devices, so you must explicitly grant specific users or groups access to specific devices. This is achieved by means of a new udev rule. First, find out which groups you're in, and choose one to use in the udev rule:
$ groups
users cdrom floppy sudo audio dip video plugdev netdev lpadmin scanner vboxusers
$
I'm going to choose the users
group for this example udev rule. As root, create a file /etc/udev/rules.d/10-umdkv2.rules
, containing these two lines:
ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="04b4", ATTR{idProduct}=="8613", GROUP="users", MODE="0660"
ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="1d50", ATTR{idProduct}=="602b", GROUP="users", MODE="0660"
That instructs the system to detect when a UMDK cart is added to the system, and allow access to members of the users
group. Without this rule, you'd have to run all the UMDK software as root, which would be a bit rubbish.
Lastly, if you're in Group A, you'll need to blacklist the usbtest
kernel module. As root, create a file /etc/modprobe.d/usbtest.conf
, containing this line:
blacklist usbtest
Finally, reboot your computer to force your changes to take effect.
For x86:
cd ${HOME}
wget -q https://dl.dropboxusercontent.com/u/80983693/umdkv2/umdk-lx86-20151220.tar.gz
tar zxf umdk-lx86-20151220.tar.gz
wget -q https://dl.dropboxusercontent.com/u/80983693/umdkv2/xtools-lx86-20151220.tar.gz
tar zxf xtools-lx86-20151220.tar.gz
And for x64:
cd ${HOME}
wget -q https://dl.dropboxusercontent.com/u/80983693/umdkv2/umdk-lx64-20151220.tar.gz
tar zxf umdk-lx64-20151220.tar.gz
wget -q https://dl.dropboxusercontent.com/u/80983693/umdkv2/xtools-lx64-20151220.tar.gz
tar zxf xtools-lx64-20151220.tar.gz
This will create two directories:
- The
umdkv2-bin
directory contains the UMDK tools - The
x-tools
directory contains the 68000 assembler, GCC compiler and GDB debugger
You can add these two directories to your system PATH like this:
export PATH=${HOME}/umdkv2-bin:${HOME}/x-tools/m68k-megadrive-elf/bin:${PATH}
You will probably want to add that line to your profile (e.g add it to ${HOME}/.bashrc
), so you don't have to type it in every time you open a new terminal window.
If you're in Group B, you can skip forward to Step 7.
With no jumpers populated, connect the LX9 board to one of your computer's USB sockets, and using your multimeter, verify that the voltage on J4's top pin is close to 5.0V. You can use the row of GNDs at the bottom as a reference point:
Next, with J4 set to USB (i.e a jumper shorting the top two pins on J4), verify that the output of REG3.3 is not significantly less than 3.3V (sorry, crappy photo): Next, with J2 populated, verify that the output of REG1.2 is not significantly less than 1.2V: All correct? Great! Next we'll start loading the firmware and testing the LX9 board.If you're in Group B, you can skip to Step 5.
First, check that the USB cable is unplugged, the bridge board is disconnected and that the jumper settings are correct (J4 in USB mode, J2 populated):
Now, tail the system log: ```console $ sudo tail -f /var/log/messages : ``` ...and then connect the USB cable. You should see something similar to this: ```console $ sudo tail -f /var/log/messages Nov 22 12:06:00 wotan kernel: [84365.200518] usb 2-1.2: new high-speed USB device number 20 using ehci-pci Nov 22 12:06:00 wotan kernel: [84365.292631] usb 2-1.2: New USB device found, idVendor=04b4, idProduct=8613 Nov 22 12:06:00 wotan kernel: [84365.292644] usb 2-1.2: New USB device strings: Mfr=0, Product=0, SerialNumber=0 Nov 22 12:06:00 wotan mtp-probe: checking bus 2, device 20: "/sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2" Nov 22 12:06:00 wotan mtp-probe: bus: 2, device: 20 was not an MTP device ``` Hit Ctrl-C and list the USB devices: ```console $ lsusb | grep 04b4 Bus 002 Device 020: ID 04b4:8613 Cypress Semiconductor Corp. CY7C68013 EZ-USB FX2 USB 2.0 Development Kit $ ``` This means that the FX2 microcontroller on the LX9 board is enumerating correctly, and is cause for a minor celebration.Next, load the FPGALink firmware into the FX2 microcontroller's RAM, using the flcli
utility:
$ flcli -i 04b4:8613 -v 1d50:602b
Attempting to open connection to FPGALink device 1d50:602b...
Loading firmware into 04b4:8613...
Awaiting renumeration.....
Attempting to open connection to FPGLink device 1d50:602b again...
Connected to FPGALink device 1d50:602b (firmwareID: 0xFFFF, firmwareVersion: 0x20140311)
$
Now, leaving the USB cable connected, add a jumper to J1:
Now load the FPGALink firmware into the FX2's EEPROM: ```console $ flcli -v 1d50:602b --eeprom=std Attempting to open connection to FPGALink device 1d50:602b... Connected to FPGALink device 1d50:602b (firmwareID: 0xFFFF, firmwareVersion: 0x20140311) Writing the standard FPGALink firmware to the FX2's EEPROM... $ ``` Now disconnect and reconnect the USB cable, and verify that the FX2 boots correctly from EEPROM: ```console $ flcli -v 1d50:602b Attempting to open connection to FPGALink device 1d50:602b... Connected to FPGALink device 1d50:602b (firmwareID: 0xFFFF, firmwareVersion: 0x20140311) $ ``` Now scan the JTAG chain, to verify that the FPGA is present: ```console $ flcli -v 1d50:602b -q A7A0A3A1 Attempting to open connection to FPGALink device 1d50:602b... Connected to FPGALink device 1d50:602b (firmwareID: 0xFFFF, firmwareVersion: 0x20140311) The FPGALink device at 1d50:602b scanned its JTAG chain, yielding: 0x24001093 $ ``` Now program the FPGA with `cksum.xsvf`: ```console $ flcli -v 1d50:602b -p J:A7A0A3A1:${HOME}/umdkv2-bin/cksum.xsvf Attempting to open connection to FPGALink device 1d50:602b... Connected to FPGALink device 1d50:602b (firmwareID: 0xFFFF, firmwareVersion: 0x20140311) Programming device... $ ``` Next, write 512KiB of random data to the FPGA, and compare the FPGA-calculated and CPU-calculated checksums: ```console $ cd ${HOME} $ dd if=/dev/urandom of=random.bin bs=1024 count=512 512+0 records in 512+0 records out 524288 bytes (524 kB) copied, 0.0650854 s, 8.1 MB/s $ flcli -v 1d50:602b -a 'w0 "random.bin";r1;r2' -b Attempting to open connection to FPGALink device 1d50:602b... Connected to FPGALink device 1d50:602b (firmwareID: 0xFFFF, firmwareVersion: 0x20140311) Executing CommFPGA actions on FPGALink device 1d50:602b... Wrote 524288 bytes (checksum 0xA8D2) to channel 0 at 41.722296 MiB/s Read 1 bytes (checksum 0x00A8) from channel 1 at 0.019463 MiB/s Read 1 bytes (checksum 0x00D2) from channel 2 at 0.008913 MiB/s 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 0000 A8 D2 .. ``` Note that in this case the CPU-calculated checksum is `0xA8D2` and the FPGA-calculated checksum is `A8 D2`. The actual checksum you get will almost certainly differ. The actual value you get doesn't matter; the important thing is that the CPU and FPGA both calculate the *same* checksum value.Before we move on, make a note of your measured USB throughput figure. Mine is 41.722296 MiB/s
. If you get something significantly less than that, try again with different USB ports and different USB cables, to see if that gets you closer to 40MiB/s. A slow USB link is an early-warning sign that UMDK's instruction-tracing capability may not work reliably for you.
Now, let's see if the FPGA's flash works OK. Program the FPGA with spi-talk.xsvf
, then use the gordon
tool (flash gordon, geddit?) to write our 512KiB of random data to the FPGA's flash, then read it back and compare:
$ flcli -v 1d50:602b -p J:A7A0A3A1:${HOME}/umdkv2-bin/spi-talk.xsvf
Attempting to open connection to FPGALink device 1d50:602b...
Connected to FPGALink device 1d50:602b (firmwareID: 0xFFFF, firmwareVersion: 0x20140311)
Programming device...
$ gordon -v 1d50:602b -t indirect:1 -w random.bin:0
Device: Micron/Numonyx/ST M25P40
Writing 0x00080000 bytes to address 0x00000000...
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
$ gordon -v 1d50:602b -t indirect:1 -r out.bin:0:0x80000
Device: Micron/Numonyx/ST M25P40
Reading 0x00080000 bytes from address 0x00000000...
$ cmp random.bin out.bin
$
Now let's see if the FPGA will boot OK from its flash. First, write the cksum.bin
file to the flash:
$ gordon -v 1d50:602b -t indirect:1 -w ${HOME}/umdkv2-bin/cksum.bin:0
Device: Micron/Numonyx/ST M25P40
Writing 0x0005327C bytes to address 0x00000000...
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
...................................................
$
Then disconnect and reconnect the USB cable, to force the FX2 and the FPGA to boot from their respective nonvolatile memories. We can verify by re-running the earlier flcli
command:
$ flcli -v 1d50:602b -a 'w0 "random.bin";r1;r2' -b
Attempting to open connection to FPGALink device 1d50:602b...
Connected to FPGALink device 1d50:602b (firmwareID: 0xFFFF, firmwareVersion: 0x20140311)
Executing CommFPGA actions on FPGALink device 1d50:602b...
Wrote 524288 bytes (checksum 0xA8D2) to channel 0 at 41.618112 MiB/s
Read 1 bytes (checksum 0x00A8) from channel 1 at 0.004541 MiB/s
Read 1 bytes (checksum 0x00D2) from channel 2 at 0.016731 MiB/s
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
0000 A8 D2 ..
$
Now let's test the SDRAM. Program the FPGA with readback.xsvf
, then write 16MiB of random data to the SDRAM, read it back and compare:
$ flcli -v 1d50:602b -p J:A7A0A3A1:${HOME}/umdkv2-bin/readback.xsvf
Attempting to open connection to FPGALink device 1d50:602b...
Connected to FPGALink device 1d50:602b (firmwareID: 0xFFFF, firmwareVersion: 0x20140311)
Programming device...
$ dd if=/dev/urandom of=random.bin bs=1M count=16
16+0 records in
16+0 records out
16777216 bytes (17 MB) copied, 1.07856 s, 15.6 MB/s
$ flcli -v 1d50:602b -a 'w0 0000000080800000;w0 "random.bin"'
Attempting to open connection to FPGALink device 1d50:602b...
Connected to FPGALink device 1d50:602b (firmwareID: 0xFFFF, firmwareVersion: 0x20140311)
Executing CommFPGA actions on FPGALink device 1d50:602b...
$ flcli -v 1d50:602b -a 'w0 0000000040800000;r0 1000000 "out.bin"'
Attempting to open connection to FPGALink device 1d50:602b...
Connected to FPGALink device 1d50:602b (firmwareID: 0xFFFF, firmwareVersion: 0x20140311)
Executing CommFPGA actions on FPGALink device 1d50:602b...
$ cmp random.bin out.bin
$
If you've got this far, congratulations. Your LX9 board has passed all the basic functional tests. The next step is to connect it to the UMDK bridge-board and plug it into your MegaDrive for the first time!
Start with the jumper configuration we ended up with in step 4:
Now use `spi-talk.xsvf` to write 512KiB of random data to the FPGA's flash again like we did in the middle of step 4 (we'll be reading it back and verifying later). ```console $ cd ${HOME} $ dd if=/dev/urandom of=random.bin bs=1024 count=512 512+0 records in 512+0 records out 524288 bytes (524 kB) copied, 0.0650854 s, 8.1 MB/s $ flcli -v 1d50:602b -p J:A7A0A3A1:${HOME}/umdkv2-bin/spi-talk.xsvf Attempting to open connection to FPGALink device 1d50:602b... Connected to FPGALink device 1d50:602b (firmwareID: 0xFFFF, firmwareVersion: 0x20140311) Programming device... $ gordon -v 1d50:602b -t indirect:1 -w random.bin:0 Device: Micron/Numonyx/ST M25P40 Writing 0x00080000 bytes to address 0x00000000... ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ ................................................................$
Now, disconnect the USB cable and *carefully* attach the bridge-board, ensuring you have the correct orientation. Then move the jumper at J4 to select EXT mode, and populate J3. Your boards should now look like this:
<p align="center"><img src="http://i.imgur.com/LvXxUjZ.jpg"/></p>
In this configuration, the LX9 is configured to get its 5V power from the MegaDrive, and to supply 3.3V power from REG3.3 to the bridge-board.
Now plug your UMDK cart into your MegaDrive, again making sure you have the correct orientation. It's safest to actually put the cart into a standard-sized game-cart enclosure - you'll need to use a file to cut a thin slot in the top of the plastic enclosure for this. If you don't care about the enclosure, just make sure you have the cartridge's orientation correct - from the front of the MegaDrive, you should see the FPGA, but the SD-Card slot should not be visible:
<p align="center"><img src="https://cdn.hackaday.io/images/6178951403040455187.jpg"/></p>
When you turn on your MegaDrive, it will be held in reset by the (uninitialised) FPGA, so you'll see a blank screen. We can now run some basic tests to verify that the MegaDrive can access the UMDK cart correctly.
First, a basic signal test:
```console
$ flcli -v 1d50:602b -p J:A7A0A3A1:${HOME}/umdkv2-bin/fpga-test.xsvf
Attempting to open connection to FPGALink device 1d50:602b...
Connected to FPGALink device 1d50:602b (firmwareID: 0xFFFF, firmwareVersion: 0x20140311)
Programming device...
$ wget -q https://dl.dropboxusercontent.com/u/80983693/umdkv2/sigtest.bin.bz2
$ bunzip2 sigtest.bin.bz2
$ loader -w sigtest.bin:0 -x 2 -t trace.bin:2048
UMDKv2 Loader Copyright (C) 2014 Chris McClelland
Putting MD in reset...
Writing SDRAM...
Releasing MD from reset...
Dumping execution trace to trace.bin:2048
................................................................
................................................................
................................................................
................................................................
Finished!
$ logread trace.bin | grep -v HEARTBEAT | head -8388250 | awk '{print $2$3$4$5}' > result.txt
$ md5sum result.txt
d5a670db486de8597e214c6849fdfacb result.txt
$
The resulting MD5 should be d5a670db486de8597e214c6849fdfacb. If you get something else, then fetch the expected trace output and compare it with yours:
$ wget -q https://dl.dropboxusercontent.com/u/80983693/umdkv2/expected.txt.bz2
$ bnzip2 expected.txt.bz2
$ diff expected.txt result.txt | less
This should help you determine what happened.
The sigtest.bin
file is just a big 8MiB blob of 68000 machine-code, without branches:
$ dis68 sigtest.bin 8 8
0x000008 move.w #21845, d0
0x00000C move.w #-21846, d1
0x000010 lea 0xFF0000, a0
0x000016 move.w d0, (a0)+
0x000018 move.w d0, (a0)+
0x00001A move.w d0, (a0)+
0x00001C move.w d0, (a0)+
0x00001E move.w d0, (a0)+
$
It first loads D0 with 0x5555
and D1 with 0xAAAA
, then points A0 at the bottom of WRAM, and then proceeds to save D0 to WRAM 32768 times using an A0 postincrement. Then it resets A0 back to the bottom of WRAM and repeats, this time saving D1:
$ dis68 sigtest.bin 0x010012 8
0x010012 move.w d0, (a0)+
0x010014 move.w d0, (a0)+
0x010016 lea 0xFF0000, a0
0x01001C move.w d1, (a0)+
0x01001E move.w d1, (a0)+
0x010020 move.w d1, (a0)+
0x010022 move.w d1, (a0)+
0x010024 move.w d1, (a0)+
$
It proceeds like this, alternating between writing 0x5555
and then 0xAAAA
to WRAM, until it reaches the very top of the 8MiB cartridge address-space, where it ends up in an infinite loop:
$ dis68 sigtest.bin 0x7FFFEE 8
0x7FFFEE move.w d1, (a0)+
0x7FFFF0 move.w d1, (a0)+
0x7FFFF2 move.w d1, (a0)+
0x7FFFF4 move.w d1, (a0)+
0x7FFFF6 move.w d1, (a0)+
0x7FFFF8 move.w d1, (a0)+
0x7FFFFA move.w d1, (a0)+
0x7FFFFC bra.s 0x7FFFFC
$
Armed with this information, the differences between your result.txt and the expected.txt should give you some hints as to what's wrong. It's likely to be a solder bridge between two pins, or a dry solder-joint somewhere. If you have trouble making deductions from the trace logs, run bzip2 result.txt
to compress your file and upload it to DropBox or similar, and post a link to the forum asking for help.
Next, a flash readback test:
$ flcli -v 1d50:602b -p J:A7A0A3A1:${HOME}/umdkv2-bin/fpga-test.xsvf
Attempting to open connection to FPGALink device 1d50:602b...
Connected to FPGALink device 1d50:602b (firmwareID: 0xFFFF, firmwareVersion: 0x20140311)
Programming device...
$ wget -q https://dl.dropboxusercontent.com/u/80983693/umdkv2/flashtest.bin
$ loader -w flashtest.bin:0 -x 2
UMDKv2 Loader Copyright (C) 2014 Chris McClelland
Putting MD in reset...
Writing SDRAM...
Releasing MD from reset...
$
Wait a few seconds for the flash readback to complete, then:
$ loader -r readback.bin:0x400000:0x80000
UMDKv2 Loader Copyright (C) 2014 Chris McClelland
Reading SDRAM...
$ cmp readback.bin random.bin
$
The purpose of this test is to ensure that the MegaDrive can read the contents of the UMDK's onboard flash chip. It does this by reading all 512KiB from flash, and copying it into SDRAM in the 0x400000-0x47FFFF
range, where it can be later read back over USB.
If the cmp
command returns an error like "readback.bin random.bin differ: byte 1234, line 123", then the test has failed. Try running the test again, this time returning a trace log:
loader -w flashtest.bin:0 -x 2 -t trace.log:512
You can then grep the resulting trace log to see what values are actually written to the 0x400000-0x47FFFF
range:
logread trace.log | grep " WB 4" | less
Now use spi-talk.xsvf
to write fpga-prod.bin
to the bottom of the flash. This is the thing that actually implements the UMDKv2's digital electronics in the FPGA:
$ flcli -v 1d50:602b -p J:A7A0A3A1:${HOME}/umdkv2-bin/spi-talk.xsvf
Attempting to open connection to FPGALink device 1d50:602b...
Connected to FPGALink device 1d50:602b (firmwareID: 0xFFFF, firmwareVersion: 0x20140311)
Programming device...
$ gordon -v 1d50:602b -t indirect:1 -w ${HOME}/umdkv2-bin/fpga-prod.bin:0
Device: Micron/Numonyx/ST M25P40
Writing 0x0005327C bytes to address 0x00000000...
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
...................................................
$
Next, write firmware.bin
to address 0x60000
of the flash. This contains the 2nd-stage bootloader, the machine-code monitor and the menu program:
$ gordon -v 1d50:602b -t indirect:1 -w ${HOME}/umdkv2-bin/firmware.bin:0x60000
Device: Micron/Numonyx/ST M25P40
Writing 0x0000C454 bytes to address 0x00060000...
................................................................
................................................................
................................................................
.....
$
If you're in Group B and have skipped forward, you will probably need to connect the LX9 board to the UMDK bridge-board, and plug the pair into your MegaDrive for the first time. First, carefully attach the bridge-board, ensuring you have the correct orientation and jumper configuration as shown below:
Now plug your UMDK cart into your MegaDrive, again making sure you have the correct orientation. It's safest to actually put the cart into a standard-sized game-cart enclosure - you'll need to use a file to cut a thin slot in the top of the plastic enclosure for this. If you don't care about the enclosure, just make sure you have the cartridge's orientation correct - from the front of the MegaDrive, you should see the FPGA, but the SD-Card slot should not be visible: When you power up the MegaDrive, you should see "MakeStuff USB MegaDrive Devkit v2" on the screen. Plug in a FAT32-formatted SD-Card (2GB or smaller) with a bunch of `.bin` game images, and you should be able to use controller 1 to select and play one of them.You can also load a .bin
game over USB using the loader
utility:
loader -w sonic.bin:0 -x 2
When connected to your PC via USB, the debugger tools I demonstrated in the videos should also work. For example, you can build a debug version of the menu program like this:
cd ${HOME}
mkdir 20151220
cd 20151220
wget -qO- http://tiny.cc/msbil | tar zxf -
cd makestuff
scripts/msget.sh makestuff/hdlmake/20151220
cd hdlmake/apps
mkdir makestuff
cd makestuff
../../../scripts/msget.sh makestuff/umdkv2
cd umdkv2/scripts
./build-sgdk.sh
cd ../m68k/menu
./dbg.sh
Now in one terminal window, run gdb-bridge
:
$ gdb-bridge -l 8000
UMDKv2 Bridge Tool Copyright (C) 2014 Chris McClelland
Waiting for GDB connection on :8000
...and in another terminal window, start DDD:
$ cd ${HOME}/20151220/makestuff/hdlmake/apps/makestuff/umdkv2/m68k/menu
$ ../../scripts/ddd.sh 8000 menu.elf
...whereupon DDD should startup, awaiting your instructions:
Happy hacking!