Running the pre-built SD-image on the FPGA
In this alternative step, we want to test standalone Ethernet functionality on an FPGA board, complete with dynamic host configuration protocol (DHCP), routing to the internet, and remote ssh.
The system will use the Ethernet 100Base-T connection at 100 MBaud to communicate with the LowRISC Linux system.
Run the pre-built FPGA demo
The files you may need:
- chip_top.bit: The tagpipe/minion/debug enabled FPGA bitstream
- boot0000.bin: Linux, Busybox and Berkley bootloader (BBL) packaged in one image (for local filing system).
- rootfs.ext2 riscv-poky root filing system ready-built for LowRISC
Download and write the bitstream
cd $TOP/fpga/board/nexys4_ddr
curl -L https://github.com/lowRISC/lowrisc-chip/releases/download/v0.5-rc2/nexys4ddr.bit > nexys4ddr.bit
curl -L https://github.com/lowRISC/lowrisc-chip/releases/download/v0.5-rc2/boot0000.bin > boot0000.bin
curl -L https://github.com/lowRISC/lowrisc-chip/releases/download/v0.5-rc2/rootfs.bzip2 | bzip2 -d > rootfs.ext2
Convert the bitstream to quad-spi memory format
vivado -mode batch -source $TOP/fpga/common/script/cfgmem.tcl -tclargs "xc7a100t_0" nexys4ddr.bit
Burn the quad-spi memory (Ensure the MODE switch is set to QSPI)
vivado -mode batch -source $TOP/fpga/common/script/program_cfgmem.tcl -tclargs "xc7a100t_0" nexys4ddr.bit.mcs
Access the boot-loader and connect to the UART console.
First check the available serial ports:
ls -l /dev/*USB*
which should result in a response similar to:
crw-rw---- 1 root dialout 188, 1 Apr 14 16:32 /dev/ttyUSB1
In this case the device is user and group only access, so you need to be a member of the group dialout to use it.
microcom -p /dev/ttyUSB1
This needs a separate terminal window as it takes over the screen. Alternatively a separate VGA display and USB keyboard may be used. You should see a display similar to the below a short delay after the PROG button is pushed.
Selftest iteration 1
Selftest matches=4/4, delay = 5
Selftest iteration 2
Selftest matches=8/8, delay = 5
Selftest iteration 3
Selftest matches=16/16, delay = 7
Selftest iteration 4
Selftest matches=32/32, delay = 13
Selftest iteration 5
Selftest matches=64/64, delay = 26
Selftest iteration 6
Selftest matches=128/128, delay = 52
Selftest iteration 7
Selftest matches=256/256, delay = 103
Selftest iteration 8
Selftest matches=375/375, delay = 151
Hello LowRISC! Thu Dec 21 18:02:20 2017
MAC = eee1:e2e3e4e5
MAC address = ee:e1:e2:e3:e4:e5.
IP Address: 192.168.0.51
Subnet Mask: 255.255.255.0
Enabling interrupts
SD-card preparation
The preparation is similar to formatting a hard disk for Linux installation on a host (the old, non-gui way). With a suitable card reader, insert the SD card (I use 8GByte for this example):
dmesg|tail
...
[98153.422033] sd 6:0:0:1: [sdc] 15564800 512-byte logical blocks: (7.97 GB/7.42 GiB)
...
We see the new disk is given the designation /dev/sdc. If your workstation is setup to mount existing partitions automatically, unmount them but do not use the eject button on the GUI. (for example: )
sudo umount /media/jrrk2/B725-19B1
sudo fdisk /dev/sdc
[sudo] password for jrrk2:
Welcome to fdisk (util-linux 2.27.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Command (m for help): p
Disk /dev/sdc: 7.4 GiB, 7969177600 bytes, 15564800 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x5c9ebcd9
Device Boot Start End Sectors Size Id Type
/dev/sdc1 2048 67583 65536 32M b W95 FAT32
/dev/sdc2 67584 1296383 1228800 600M 83 Linux
/dev/sdc3 1296384 3393535 2097152 1G 82 Linux swap / Solaris
Command (m for help): p
Disk /dev/sdc: 7.4 GiB, 7969177600 bytes, 15564800 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x074e0e18
The disk will typically be empty or have one large DOS partition, if not use the o command to create a new table
Command (m for help): o
Created a new DOS disklabel with disk identifier 0x074e0e18.
We proceed to create the partitions as follows:
Command (m for help): n
Partition type
p primary (0 primary, 0 extended, 4 free)
e extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1):
First sector (2048-15564799, default 2048):
Last sector, +sectors or +size{K,M,G,T,P} (2048-15564799, default 15564799): +32M
Created a new partition 1 of type 'Linux' and of size 32 MiB.
Command (m for help): t
Selected partition 1
Partition type (type L to list all types): b
Changed type of partition 'Linux' to 'W95 FAT32'.
Command (m for help): n
Partition type
p primary (1 primary, 0 extended, 3 free)
e extended (container for logical partitions)
Select (default p): p
Partition number (2-4, default 2):
First sector (67584-15564799, default 67584):
Last sector, +sectors or +size{K,M,G,T,P} (67584-15564799, default 15564799): +600M
Created a new partition 2 of type 'Linux' and of size 600 MiB.
Command (m for help): n
Partition type
p primary (2 primary, 0 extended, 2 free)
e extended (container for logical partitions)
Select (default p): p
Partition number (3,4, default 3):
First sector (1296384-15564799, default 1296384):
Last sector, +sectors or +size{K,M,G,T,P} (1296384-15564799, default 15564799): +1G
Created a new partition 3 of type 'Linux' and of size 1 GiB.
Command (m for help): t
Partition number (1-3, default 3):
Partition type (type L to list all types): 82
Changed type of partition 'Linux' to 'Linux swap / Solaris'.
Command (m for help): p
Disk /dev/sdc: 7.4 GiB, 7969177600 bytes, 15564800 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x074e0e18
Device Boot Start End Sectors Size Id Type
/dev/sdc1 2048 67583 65536 32M b W95 FAT32
/dev/sdc2 67584 1296383 1228800 600M 83 Linux
/dev/sdc3 1296384 3393535 2097152 1G 82 Linux swap / Solaris
Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Re-reading the partition table failed.: Device or resource busy
The kernel still uses the old table. The new table will be used at the next reboot or after you run partprobe(8) or kpartx(8).
To ensure the new partitions are recognised, remove and reinsert the card.
Setting the partitions (use the image downloaded at the top of this page)
sudo mkfs.msdos /dev/sdc1
sudo dd if=rootfs.ext2 of=/dev/sdc2 bs=64M
sudo mkswap /dev/sdc3
Optional: set up the time-server
sudo vi /etc/xinetd.d/time
#Change the first occurence of "disable=yes" to "disable=no". This enables the time service.
sudo /etc/init.d/xinetd restart
SD booting (kernel via Ethernet)
cd $TOP/fpga/board/nexys4_ddr
make ethersd
SD booting (standalone)
cd $TOP/fpga/board/nexys4_ddr
cp *.bin /media/jrrk2/26CD-9823/ # or wherever your SD-card partition is mounted
If you did not take advantage of the pre-defined images mentioned earlier you can prepare the board as follows:
make boot cfgmem-updated program-cfgmem-updated
The default boot loader will choose how to boot according to the DIP switches as follows:
SW0 on: boot from RAM (only useful if you have compiled in the trace debugger) SW1 on: boot from SD-card SW2 on: boot from Ethernet as per the previous section
SW7-3: turn these off SW15-12: select a suitable unique MAC address variant for your network (allows multiple LowRISCs to talk)
After inserting the SD-card in the Nexys4-DDR unit, and pressing PROG, you should see a display similar to the previous section, ending with the following. By contrast with the NFS-root, etherboot method, the eth0 device is free to take up any allocated address. In conjunction with the support VGA text screen and USB-keyboard, emulation of a variety of standalone computing tasks is possible.
Setting the clock ...
[ 11.350000] mmc0: new SDHC card at address 0007
[ 11.380000] blk_queue_max_hw_sectors: set to minimum 8
[ 11.400000] mmcblk0: mmc0:0007 SD08G 7.42 GiB
[ 11.480000] mmcblk0: p1 p2 p3
Waiting for the sd card ...
Mounting the sd partition ...
[ 22.630000] EXT2-fs (mmcblk0p2): warning: mounting unchecked fs, running e2fsck is recommended
Switch to sd root
[ 33.090000] random: nonblocking pool is initialized
INIT: version 2.88 booting
bootlogd: cannot find console device 4:0 under /dev
hwclock: can't open '/dev/misc/rtc': No such file or directory
INIT: Entering runlevel: 2
Configuring network interfaces... udhcpc (v1.24.1) started
Sending discover...
Sending select for 192.168.0.106...
Lease of 192.168.0.106 obtained, lease time 86400
/etc/udhcpc.d/50default: Adding DNS 192.168.0.1
done.
Starting Dropbear SSH server: dropbear.
hwclock: can't open '/dev/misc/rtc': No such file or directory
Starting syslogd/klogd: done
Poky (Yocto Project Reference Distro) 2.0+snapshot-20171219 qemuriscv64 /dev/console
qemuriscv64 login:
The first boot will take considerably longer than subsequent boots due to the ssh keys having to be regenerated. In addition at first there will be no root password. You should login as root and set this up with the ‘passwd’ command. Any changes you make will be stored locally on the SD-card, so it is important to shutdown the server properly with the ‘halt’ command.
Mount an SD card inside RISC-V Linux
The root partition on /dev/mmcblk0p2 will have been mounted already during pre-init. This happens during the following script:
#!/bin/busybox ash
/bin/busybox install -s
/bin/busybox ifconfig eth0 192.168.0.51 up
/bin/busybox echo Setting the clock ...
/bin/busybox rdate -s 192.168.0.53
/bin/busybox echo Waiting for the sd card ...
/bin/busybox sleep 10
/bin/busybox echo Mounting the sd partition ...
/bin/busybox mount -t ext2 /dev/mmcblk0p2 /mnt || /bin/busybox ash
# Mount the /proc and /sys filesystems.
/bin/busybox mount -t proc none /mnt/proc
/bin/busybox mount -t sysfs none /mnt/sys
/bin/busybox mount -t devtmpfs udev /mnt/dev
/bin/busybox mkdir -p /mnt/dev/pts
/bin/busybox mount -t devpts devpts /mnt/dev/pts
/bin/busybox mount -t tmpfs tmpfs /mnt/tmp
# Do your stuff here.
/bin/busybox echo "Switch to sd root"
# Boot the real thing.
exec /bin/busybox switch_root /mnt /sbin/init
Care should be taken if modifying this script to ensure the RAM-disk is freed at the end of the operation and not left busy. Also ensure that init is not killed which will kill the whole system.
The SD card is permanently inserted, it should look like:
cat /proc/partitions
major minor #blocks name
179 0 7782400 mmcblk0
179 1 32768 mmcblk0p1
179 2 614400 mmcblk0p2
179 3 1048576 mmcblk0p3
To mount a DOS file system from this card:
root@qemuriscv64:~# mount /dev/mmcblk0p1 /mnt
root@qemuriscv64:~# ls -l /mnt
drwxr-xr-x 2 root root 2048 Jan 1 1980 DIR
-rwxr-xr-x 1 root root 5272272 Dec 22 11:22 boot0000.bin
-rwxr-xr-x 1 root root 5272272 Dec 22 11:22 boot0001.bin
After you finished with the SD card, remember to unmount it.
umount /mnt
##Test the network performance (iperf3 -s needs to be running on the selected server)
root@qemuriscv64:~# iperf3 -c 192.168.0.53 -u -b 2M
Connecting to host 192.168.0.53, port 5201
[ 5] local 192.168.0.106 port 44078 connected to 192.168.0.53 port 5201
[ ID] Interval Transfer Bitrate Total Datagrams
[ 5] 0.00-1.01 sec 215 KBytes 1.75 Mbits/sec 152
[ 5] 1.01-2.01 sec 205 KBytes 1.68 Mbits/sec 145
[ 5] 2.01-3.00 sec 209 KBytes 1.72 Mbits/sec 148
[ 5] 3.00-4.00 sec 208 KBytes 1.71 Mbits/sec 147
[ 5] 4.00-5.01 sec 209 KBytes 1.71 Mbits/sec 148
[ 5] 5.01-6.01 sec 212 KBytes 1.74 Mbits/sec 150
[ 5] 6.01-7.00 sec 209 KBytes 1.72 Mbits/sec 148
[ 5] 7.00-8.00 sec 211 KBytes 1.73 Mbits/sec 149
[ 5] 8.00-9.01 sec 212 KBytes 1.73 Mbits/sec 150
[ 5] 9.01-10.00 sec 211 KBytes 1.73 Mbits/sec 149
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Jitter Lost/Total Datagrams
[ 5] 0.00-10.00 sec 2.05 MBytes 1.72 Mbits/sec 0.000 ms 0/1486 (0%) sender
[ 5] 0.00-10.08 sec 2.05 MBytes 1.71 Mbits/sec 0.419 ms 0/1486 (0%) receiver
iperf Done.
##Add a swap partition
The final partition is designated as swap. This will be handy if you wish to attempt heavy duty tasks such as compilation.
root@qemuriscv64:~# swapon /dev/mmcblk0p3
[ 983.110000] Adding 1048572k swap on /dev/mmcblk0p3. Priority:-1 extents:1 across:1048572k SS
root@qemuriscv64:~# free
total used free shared buffers cached
Mem: 111320 10088 101232 196 36 5200
-/+ buffers/cache: 4852 106468
Swap: 1048572 0 1048572
root@qemuriscv64:~#
##Using dropbear ssh server
Using the serial console is inconvenient because it does not support cut and paste or line editing. Now we have network connectivity we can use ssh via dropbear (a simplified alternative to openssh-server) to provide more convenient access. SSH requires a password so we set one up as follows: (replace jrrk2 with your own username)
root@qemuriscv64:~# adduser jrrk2
adduser: warning: can't lock '/etc/passwd': Invalid argument
addgroup: warning: can't lock '/etc/group': Invalid argument
Changing password for jrrk2
New password: Password
Retype password: Password
passwd: warning: can't lock '/etc/passwd': Invalid argument
Password for jrrk2 changed by root
Since we use dhcpc by default in SD-root mode, we need to discover the IP-addr of the lowrisc as follows:
root@qemuriscv64:~# ifconfig -a
eth0 Link encap:Ethernet HWaddr EE:E1:E2:E3:E4:E5
inet addr:192.168.0.106 Bcast:192.168.0.255 Mask:255.255.255.0
UP BROADCAST RUNNING MTU:1500 Metric:1
RX packets:829 errors:0 dropped:251 overruns:0 frame:0
TX packets:22 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:156188 (152.5 KiB) TX bytes:1966 (1.9 KiB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
The inet addr mentioned above may be pasted into a new server window as follows:
jrrk2@jrrk2-iMac:/local/scratch/jrrk2/lowrisc-site$ ssh 192.168.0.106
The authenticity of host '192.168.0.106 (192.168.0.106)' can't be established.
RSA key fingerprint is SHA256:J1wLm+WjAMH5stKQnZUE4BZuYmBMgt2IuCUM1bWt3n4.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.0.106' (RSA) to the list of known hosts.
jrrk2@192.168.0.106's password:
##Download and compile an example program
Name servers and routers, were setup by DHCP, so we can start and download an example straight away. Notice that the prompt is changed from # to $, since we are now running unprivileged under ssh. This example tests the name server client and gateway routing functionality.
qemuriscv64:~$ wget http://www.ioccc.org/1988/phillipps.c
Connecting to www.ioccc.org (206.197.161.153:80)
phillipps.c 100% |******************************************| 878 0:00:00 ETA
Now we can try a compilation (The first compile will be slower because all files have to be fetched from SD. Subsequent compilations can make use of cached inodes):
qemuriscv64:~$ riscv64-poky-linux-gcc phillipps.c
phillipps.c:1:1: warning: return type defaults to 'int' [-Wimplicit-int]
main(t,_,a )
^
phillipps.c: In function 'main':
phillipps.c:1:1: warning: type of 't' defaults to 'int' [-Wimplicit-int]
phillipps.c:1:1: warning: type of '_' defaults to 'int' [-Wimplicit-int]
phillipps.c:37:1: warning: implicit declaration of function 'putchar' [-Wimplicit-function-declaration]
putchar(31[a]):
Optionally, check what is there:
qemuriscv64:~$ ls -l ./a.out
-rwxr-xr-x 1 jrrk2 jrrk2 10224 Dec 23 14:15 ./a.out
qemuriscv64:~$ file a.out
a.out: ELF 64-bit LSB executable, UCB RISC-V, version 1 (SYSV), dynamically linked, interpreter /lib/ld.so.1, for GNU/Linux 2.6.32, BuildID[sha1]=f354f636d4c6e12527810387f0fe700e1b9b070b, not stripped
qemuriscv64:~$ date
Sat Dec 23 14:41:22 UTC 2017
qemuriscv64:~$
This date calls for a seasonal message (execute the program):
root@qemuriscv64:~$ ./a.out
On the first day of Christmas my true love gave to me
a partridge in a pear tree.
On the second day of Christmas my true love gave to me
two turtle doves
and a partridge in a pear tree.
On the third day of Christmas my true love gave to me
three french hens, two turtle doves
and a partridge in a pear tree.
On the fourth day of Christmas my true love gave to me
four calling birds, three french hens, two turtle doves
and a partridge in a pear tree.
On the fifth day of Christmas my true love gave to me
five gold rings;
four calling birds, three french hens, two turtle doves
and a partridge in a pear tree.
On the sixth day of Christmas my true love gave to me
six geese a-laying, five gold rings;
four calling birds, three french hens, two turtle doves
and a partridge in a pear tree.
On the seventh day of Christmas my true love gave to me
seven swans a-swimming,
six geese a-laying, five gold rings;
four calling birds, three french hens, two turtle doves
and a partridge in a pear tree.
On the eighth day of Christmas my true love gave to me
eight maids a-milking, seven swans a-swimming,
six geese a-laying, five gold rings;
four calling birds, three french hens, two turtle doves
and a partridge in a pear tree.
On the ninth day of Christmas my true love gave to me
nine ladies dancing, eight maids a-milking, seven swans a-swimming,
six geese a-laying, five gold rings;
four calling birds, three french hens, two turtle doves
and a partridge in a pear tree.
On the tenth day of Christmas my true love gave to me
ten lords a-leaping,
nine ladies dancing, eight maids a-milking, seven swans a-swimming,
six geese a-laying, five gold rings;
four calling birds, three french hens, two turtle doves
and a partridge in a pear tree.
On the eleventh day of Christmas my true love gave to me
eleven pipers piping, ten lords a-leaping,
nine ladies dancing, eight maids a-milking, seven swans a-swimming,
six geese a-laying, five gold rings;
four calling birds, three french hens, two turtle doves
and a partridge in a pear tree.
On the twelfth day of Christmas my true love gave to me
twelve drummers drumming, eleven pipers piping, ten lords a-leaping,
nine ladies dancing, eight maids a-milking, seven swans a-swimming,
six geese a-laying, five gold rings;
four calling birds, three french hens, two turtle doves
and a partridge in a pear tree.
root@qemuriscv64:~$