Networking on CycloneV

Hello, I am trying to get networking up on my CycloneV.

The reference guide says that the chip has two MACs. When I boot the kernel, it seems to freeze and I get no output.

U-Boot SPL 2019.10-02867-g8c2b33ad5c-dirty (May 05 2020 - 23:40:01 -0400)
Trying to boot from MMC1


U-Boot 2019.10-02867-g8c2b33ad5c-dirty (May 05 2020 - 23:40:01 -0400)

CPU:   Altera SoCFPGA Platform
FPGA:  Altera Cyclone V, SE/A5 or SX/C5 or ST/D5, version 0x0
BOOT:  SD/MMC Internal Transceiver (3.0V)
       Watchdog enabled
DRAM:  1 GiB
MMC:   dwmmc0@ff704000: 0
Loading Environment from MMC... *** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
Model: Altera SOCFPGA Cyclone V SoC Development Kit
Net:
Warning: ethernet@ff702000 (eth0) using random MAC address - 06:9f:55:fd:bb:af
eth0: ethernet@ff702000
Hit any key to stop autoboot:  0
708 bytes read in 3 ms (230.5 KiB/s)
## Executing script at 02000000
7007204 bytes read in 384 ms (17.4 MiB/s)
4978264 bytes read in 276 ms (17.2 MiB/s)
26612 bytes read in 7 ms (3.6 MiB/s)
## Flattened Device Tree blob at 00001000
   Booting using the fdt blob at 0x001000
   Loading Device Tree to 3bf3a000, end 3bf437f3 ... OK

Starting kernel ...

My hardware setup looks like this
eth

Using the u-boot version documented in the guide as well as the Linux kernel and rootfs documented by that build system

Not sure how the device tree generated by the kernel from that guide (socfpga_cyclone5_socdk.dtb) is going to know about the MAC.

I am lost for where to start debugging. Has anyone got networking up on CycloneV using the kernel and rootfs from the guide?

Update:
Built latest bootloader without adding script and got into Linux. It appeared that it was trying DHCP discovery during kernel boot.

This is my current boot script
setenv fdtimage socfpga_cyclone5_socdk.dtb
setenv bootimage zImage
setenv root /dev/mmcblk0p2

setenv fpga 0
setenv fdtaddr 0x1000
setenv kerneladdr 0x200000
setenv fpgadata 0x2000000
setenv bootargs console=ttyS0,115200 debug ignore_loglevel earlyprintk=ttyS0,115200 break=y root=${root} rootwait rw ${bootargs_extra} ${runlevel}

# load FPGA config
ext4load mmc 0:2 0x2000000 /boot/hps_only.rbf
fpga load 0 0x2000000 7007204

# load kernel and DT
ext4load mmc 0:2 ${kerneladdr} /boot/${bootimage}
ext4load mmc 0:2 ${fdtaddr} /boot/${fdtimage}

# setup bridges
#bridge enable 0xffffffff

# boot kernel
bootz ${kerneladdr} - ${fdtaddr}

There must be something in the environment variables for the normal boot (not my script, but exactly same steps as guide) that u-boot does to set up Ethernet for the kernel. If anyone knows what this is, I would greatly appreciate it, else I will probably have to sift through u-boot manifest constants and tweak my script.

Did you try to set an IP address in U-Boot and ping another host in your network? Does this work?

Check dmesg for “eth” message. It should look like this:

dmesg | grep eth
[    1.948501] socfpga-dwmac ff702000.ethernet: PTP uses main clock
[    1.954788] socfpga-dwmac ff702000.ethernet: Ring mode enabled
[    1.960603] socfpga-dwmac ff702000.ethernet: DMA HW capability register supported
[    1.968086] socfpga-dwmac ff702000.ethernet: Enhanced/Alternate descriptors
[    1.975043] socfpga-dwmac ff702000.ethernet: Extended descriptors not supported
[    1.982340] socfpga-dwmac ff702000.ethernet: RX Checksum Offload Engine supported
[    1.989793] socfpga-dwmac ff702000.ethernet: COE Type 2
[    1.995011] socfpga-dwmac ff702000.ethernet: TX Checksum insertion supported
[    4.651489] socfpga-dwmac ff702000.ethernet eth0: registered PTP clock

My DT contains the following node to enable ethernet:

&gmac1 {
        status = "okay";
        phy-mode = "rgmii";

        txd0-skew-ps = <0>; /* -420ps */
        txd1-skew-ps = <0>; /* -420ps */
        txd2-skew-ps = <0>; /* -420ps */
        txd3-skew-ps = <0>; /* -420ps */
        rxd0-skew-ps = <420>; /* 0ps */
        rxd1-skew-ps = <420>; /* 0ps */
        rxd2-skew-ps = <420>; /* 0ps */
        rxd3-skew-ps = <420>; /* 0ps */
        txen-skew-ps = <0>; /* -420ps */
        txc-skew-ps = <1860>; /* 960ps */
        rxdv-skew-ps = <420>; /* 0ps */
        rxc-skew-ps = <1680>; /* 780ps */

        max-frame-size = <3800>;
};

BTW: Your U-Boot currently sets a random MAC on each boot. You can set a static MAC address by setting the ethaddr variable in U-Boot.

I was able to ping the board after I booted with the normal u-boot (no script). It was the same Quartus image and device tree that I used for the script that did not boot the kernel, and for the normal u-boot (no script) that booted into the kernel and was able to be pinged.

This proves the problem is something in u-boot. Something that normally happens to help set up Ethernet is not happening when I run the script. What exactly that is, I will have to investigate. Maybe I can stop u-boot and start printing environment variables and looking through source code.

It is probably in the environment variable
CONFIG_EXTRA_ENV_SETTINGS

or

CONFIG_BOOTCOMMAND “run distro_bootcmd”

One thing that U-Boot does is setting the I/O multiplexors. I think the U-Boot default is to set the I/O pins as required by the GHRD. If you have changed any IO pins you would have to regenerate the “qts” headers in U-Boot.

That is possible. I will double check to make sure I did that step in the u-boot with the script. I am pretty sure I do that every time as directed by the guide. My thought is that I might be interrupting normal u-boot execution with the script before it has a chance to actually do that part.

I am pretty sure I set up the I/O exactly the same as GHRD. I have gotten the same Quartus design to work (bring up Ethernet/networking in Linux) when I do not interrupt the default execution of u-boot by using the script.

UPDATE:
A good boot looks like this in the logs.

Warning: ethernet@ff702000 (eth0) using random MAC address - 82:58:a9:bf:3a:93
eth0: ethernet@ff702000
Hit any key to stop autoboot:  0
switch to partitions #0, OK
mmc0 is current device
Scanning mmc 0:1...
Found /extlinux/extlinux.conf
Retrieving file: /extlinux/extlinux.conf
157 bytes read in 4 ms (38.1 KiB/s)
1:      Linux Default
Retrieving file: /extlinux/../zImage
4978264 bytes read in 267 ms (17.8 MiB/s)
append: root=/dev/mmcblk0p2 rw rootwait earlyprintk console=ttyS0,115200n8
Retrieving file: /extlinux/../socfpga_cyclone5_socdk.dtb
26612 bytes read in 6 ms (4.2 MiB/s)
## Flattened Device Tree blob at 02000000
   Booting using the fdt blob at 0x2000000
   Loading Device Tree to 09ff6000, end 09fff7f3 ... OK

Starting kernel ...

Deasserting all peripheral resets
[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Linux version 5.4.23-36409-gb6dad2fd8d54 (jfrye@jfrye-Inspiron-5547) (gcc version 4.8.3 20140401 (prerelease) (crosstool-NG linaro-1.13.1-4.8-2014.04 - Linaro GCC 4.8-2014.04)) #1 SMP Thu Apr 30 22:33:54 EDT 2020

I printed the entire env

arch=arm
baudrate=115200
board=cyclone5-socdk
board_name=cyclone5-socdk
boot_a_script=load ${devtype} ${devnum}:${distro_bootpart} ${scriptaddr} ${prefix}${script}; source ${scriptaddr}
boot_efi_binary=if fdt addr ${fdt_addr_r}; then bootefi bootmgr ${fdt_addr_r};else bootefi bootmgr ${fdtcontroladdr};fi;load ${devtype} ${devnum}:${distro_bootpart} ${kernel_addr_r} efi/boot/bootarm.efi; if fdt addr ${fdt_addr_r}; then bootefi ${kernel_addr_r} ${fdt_addr_r};else bootefi ${kernel_addr_r} ${fdtcontroladdr};fi
boot_extlinux=sysboot ${devtype} ${devnum}:${distro_bootpart} any ${scriptaddr} ${prefix}${boot_syslinux_conf}
boot_net_usb_start=usb start
boot_prefixes=/ /boot/
boot_script_dhcp=boot.scr.uimg
boot_scripts=boot.scr.uimg boot.scr
boot_syslinux_conf=extlinux/extlinux.conf
boot_targets=mmc0 qspi pxe dhcp
bootcmd=run distro_bootcmd
bootcmd_dhcp=run boot_net_usb_start; if dhcp ${scriptaddr} ${boot_script_dhcp}; then source ${scriptaddr}; fi;setenv efi_fdtfile ${fdtfile}; if test -z "${fdtfile}" -a -n "${soc}"; then setenv efi_fdtfile ${soc}-${board}${boardver}.dtb; fi; setenv efi_old_vci ${bootp_vci};setenv efi_old_arch ${bootp_arch};setenv bootp_vci PXEClient:Arch:00010:UNDI:003000;setenv bootp_arch 0xa;if dhcp ${kernel_addr_r}; then tftpboot ${fdt_addr_r} dtb/${efi_fdtfile};if fdt addr ${fdt_addr_r}; then bootefi ${kernel_addr_r} ${fdt_addr_r}; else bootefi ${kernel_addr_r} ${fdtcontroladdr};fi;fi;setenv bootp_vci ${efi_old_vci};setenv bootp_arch ${efi_old_arch};setenv efi_fdtfile;setenv efi_old_arch;setenv efi_old_vci;
bootcmd_mmc0=devnum=0; run mmc_boot
bootcmd_pxe=run boot_net_usb_start; dhcp; if pxe get; then pxe boot; fi
bootcmd_qspi=run qspiload; run qspiboot
bootdelay=2
bootm_size=0xa000000
bootmode=sd
cpu=armv7
distro_bootcmd=for target in ${boot_targets}; do run bootcmd_${target}; done
efi_dtb_prefixes=/ /dtb/ /dtb/current/
fatscript=if fatload mmc 0:1 ${scriptaddr} ${scriptfile};then source ${scriptaddr}; fi
fdt_addr_r=0x02000000
fdt_size=0x00010000
fdtcontroladdr=3bf43080
fdtfile=socfpga_cyclone5_socdk.dtb
fpgatype=cv_se_a5
kernel_addr_r=0x01000000
kernel_size=0x005d0000
load_efi_dtb=load ${devtype} ${devnum}:${distro_bootpart} ${fdt_addr_r} ${prefix}${efi_fdtfile}
loadaddr=0x01000000
mmc_boot=if mmc dev ${devnum}; then devtype=mmc; run scan_dev_for_boot_part; fi
prog_core=if load mmc 0:1 ${loadaddr} fit_spl_fpga.itb;then fpga loadmk 0 ${loadaddr}:fpga-core-1; fi
pxefile_addr_r=0x02200000
qspi_fdt_addr=0x00220000
qspi_kernel_addr=0x00230000
qspiboot=setenv bootargs earlycon root=/dev/mtdblock1 rw rootfstype=jffs2; bootz ${kernel_addr_r} - ${fdt_addr_r}
qspiload=sf probe; sf read ${kernel_addr_r} ${qspi_kernel_addr} ${kernel_size}; sf read ${fdt_addr_r} ${qspi_fdt_addr} ${fdt_size}
ramdisk_addr_r=0x02300000
scan_dev_for_boot=echo Scanning ${devtype} ${devnum}:${distro_bootpart}...; for prefix in ${boot_prefixes}; do run scan_dev_for_extlinux; run scan_dev_for_scripts; done;run scan_dev_for_efi;
scan_dev_for_boot_part=part list ${devtype} ${devnum} -bootable devplist; env exists devplist || setenv devplist 1; for distro_bootpart in ${devplist}; do if fstype ${devtype} ${devnum}:${distro_bootpart} bootfstype; then run scan_dev_for_boot; fi; done; setenv devplist
scan_dev_for_efi=setenv efi_fdtfile ${fdtfile}; if test -z "${fdtfile}" -a -n "${soc}"; then setenv efi_fdtfile ${soc}-${board}${boardver}.dtb; fi; for prefix in ${efi_dtb_prefixes}; do if test -e ${devtype} ${devnum}:${distro_bootpart} ${prefix}${efi_fdtfile}; then run load_efi_dtb; fi;done;if test -e ${devtype} ${devnum}:${distro_bootpart} efi/boot/bootarm.efi; then echo Found EFI removable media binary efi/boot/bootarm.efi; run boot_efi_binary; echo EFI LOAD FAILED: continuing...; fi; setenv efi_fdtfile
scan_dev_for_extlinux=if test -e ${devtype} ${devnum}:${distro_bootpart} ${prefix}${boot_syslinux_conf}; then echo Found ${prefix}${boot_syslinux_conf}; run boot_extlinux; echo SCRIPT FAILED: continuing...; fi
scan_dev_for_scripts=for script in ${boot_scripts}; do if test -e ${devtype} ${devnum}:${distro_bootpart} ${prefix}${script}; then echo Found U-Boot script ${prefix}${script}; run boot_a_script; echo SCRIPT FAILED: continuing...; fi; done
scriptaddr=0x02100000
scriptfile=u-boot.scr
soc=socfpga
socfpga_legacy_reset_compat=1
stderr=serial
stdin=serial
stdout=serial
ubifs_boot=env exists bootubipart || env set bootubipart UBI; env exists bootubivol || env set bootubivol boot; if ubi part ${bootubipart} && ubifsmount ubi${devnum}:${bootubivol}; then devtype=ubi; run scan_dev_for_boot; fi
usb_boot=usb start; if usb dev ${devnum}; then devtype=usb; run scan_dev_for_boot_part; fi
vendor=altera
ver=U-Boot 2019.10-02867-g8c2b33ad5c-dirty (May 07 2020 - 21:35:59 -0400)

The logs would suggest it is using syslinux to boot, thus the extlinux.conf. It basically falls through to
`

scan_dev_for_extlinux=if test -e ${devtype} ${devnum}:${distro_bootpart} ${prefix}${boot_syslinux_conf}; then echo Found ${prefix}${boot_syslinux_conf}; run boot_extlinux; echo SCRIPT FAILED: continuing…; fi

and doesn’t fail, so it boots. I am not super familiar with syslinux booting. I am going to dig a bit and see if I can’t see where this is setup.

`

Here is the simple solution. Write your script to load the FPGA, then hand execution back to u-boot so it can do what it is currently doing right. In the source code, point to your call script, then at the end of your call script, point to the variable that
`

CONFIG_BOOTCOMMAND

is pointing to, namely

`

distro_bootcmd

Here is the full script

# load FPGA config
ext4load mmc 0:2 0x2000000 /boot/hps_only.rbf
fpga load 0 0x2000000 7007204

# load kernel and DT
ext4load mmc 0:2 ${kerneladdr} /boot/${bootimage}
ext4load mmc 0:2 ${fdtaddr} /boot/${fdtimage}

# setup bridges
#bridge enable 0xffffffff

run distro_bootcmd

with the rbf in the ext4 file system in the /boot directory.
`

For the rootfs side of the development, add
`

CORE_IMAGE_EXTRA_INSTALL += “openssh”

`

to your local.conf and you will get openssh server and it will start during kernel boot