OpenWiFi - How to use ZYNQ SDR in Linux mode


You are not allowed to download any native file from the zc706 board. The source files are available at openwifi github repository.

Boot Linux

The following steps describe how to run an experiment using the zc706 ZYNQ SDR in Linux mode from JTAG. Please download to continue.

  1. Make a reservation of one zc706zynqSDR and its corresponding host machine, currently 3 zc706zynqSDR available, for details refer to Hardware Info ZYNQ SDR.
  2. Start an experiment with one SDR and its corresponding host, eg apuV4 and zc706zyncSDR2. Do not draw any links between the two nodes. Do not specify any image for the nodes, in this case the default image will be used.
  3. After experiment is started, reboot the zc706 board by right click on the zc706 board in jFed, select reboot and then select reboot OS.
  4. Log into the host and establish serial connection to the zc706 board using minicom, launched as follows. In the Serial port setup, device should be /dev/ttyUSB1 on APU and /dev/ttyUSB0 on server16, Hardware Flow Control should be disabled by entering F in the minicom console
sudo apt-get install minicom
sudo minicom -s
  1. Upload the host node, unzip it, you will get the directory openwifijtagfiles
  2. In the ssh terminal, cd openwifijtagfiles ; source /share/xilinx/Vivado/2017.4/ and then execute xsdb. If you experience runtime error similar to the one listed below, it may be caused by environment varialbe seetings, try unset LC_PAPER; unset LC_ADDRESS ; unset LC_MONETARY; unset LC_NUMERIC ; unset LC_TELEPHONE ; unset LC_IDENTIFICATION ; unset LC_MEASUREMENT ; unset LC_TIME; unset LC_NAME ;
Got $RDI_APPROOT: /share/xilinx/Vivado/2017.4
terminate called after throwing an instance of 'std::runtime_error'
what():  locale::facet::_S_create_c_locale name not valid
/share/xilinx/Vivado/2017.4/bin/loader: line 194:  6199 Aborted
  1. In the xsdb console, execute source dow_fsblonly.tcl, after this step, get ready to interrupt uboot auto start in serial console by hitting any key, when you are ready, execute in xsdb console con.
    • If you don’t have u-boot running and see messages such as Unable to open file BOOT.BIN, please refer to the subject Restore rootfs if SD card is corrupted in Advanced Topics.
    • Please note that the first stage boot loader (fsbl) in the zip file is compiled based on openwifi-v1.1.0, if you are using a different openwifi version, you might need to recompile the fsbl, using the script.
    • Please note that the fsbl will use whatever FPGA bitstream that is available on the SD card, refer to Update Bitstream if you would like to run a different FPGA bitstream.
    • If you see error such as no targets found with “name =~”APU”“. available targets:*, please reboot the zc706 board, wait a while and then execute the tcl script again.
  2. When u-boot autoboot is stopped, execute disconnect in xsdb console, and execute run uenvboot in serial console.
  3. Wait and see… after this command normally linux should be booted. Give an IP address of eth0 on zc706 by executing ifconfig eth0 You may now also log into the board via ssh, as explained in Initial configuration of OpenWiFi.

Update Bitstream

If you need to update the bitstream running on the FPGA, you need to regenerate BOOT.BIN file and write it to the SD card, this is explained in the following steps.

  1. Generate files on your local machine:
    • Make sure you have the Xilinx SDK installed, setup the enviornment by running source /Your/Path/To/SDK/2017.4/
    • Copy the new system.hdf file into openwifijtagfiles directory, the system.hdf is generated after compiling the FPGA project following README of openwifi-hw repository.
    • Compile new BOOT.BIN, fsbl.elf by ./ system.hdf u-boot.elf, you will find the new files in output_boot_bin directory
  2. Upload the new BOOT.BIN, fsbl.elf from your local machine to the host node, copy them to the openwifijtagfiles directory.
  3. Boot linux on zc706 as explained in the previous section, make sure you have network connection to the board, log into the zc706board, and mount the boot partition by `` mkdir /sdcard ; mount /dev/mmcblk0p1 /sdcard/ ``
  4. Copy files from the host node to zc706
    • scp output_boot_bin/BOOT.BIN root@
    • copy other files, eg devicetree.dtb, uImage if necessary in the same way.
    • update kernel modules if needed as explained on the openwifi repository.
    • update user space spcripts if needed as explained on the openwifi repository.
    • after copying the files, very important, go to the terminal of zc706 and execute umount /sdcard.
  5. On the host node, make sure your newly generated fsbl.elf is in the same folder as the dow_onlyfsbl.tcl script
  6. Power cycle the zc706 board, first execute shutdown now on the zc706 and then power cycle the board in jFed.
  7. Boot the zc706 as explained in the Boot Linux session to use the new configuration.

Initial configuration of OpenWiFi

Bring up the correct network interface on the host to connect to the ZYNQ board:

  • Eg, on apuV4 run:
sudo ifconfig eth2 up ; sudo ifconfig eth2 ; ping
  • Login to the zc706 board from the apuV4, the default password is openwifi, however it might be a different one (different image or changed by other users), just set a new password with passwd command in serial console if you cannot log in.
ssh root@ (password: openwifi)
  • For the rest please follow the quick start section of Openwifi
  • It is possible that you need to manually select antenna, please refer to the Hardware Info ZYNQ SDR to determine which antennas you need, for instance to select rx1 tx2, you need to run ~/openwifi/ rx1 tx2. You need to run this after ./, as the setting will be overwritten each time you load the sdr module.
  • Openwifi receiver uses Xilinx Viterbi core under evaluation license, this core will be disabled after a while. You will observe no SSID reported by iw sdr0 scan command, or if you observe the interupt you see the rx interrupt no longer changes (the 298 number in the sample command and results below). Then you need to power cycle the board and reboot linux.
root@analog:~# cat /proc/interrupts | grep sdr
     53:        298          0     GIC-0  62 Edge      sdr,rx_pkt_intr

Experiment 1: openwifi NIC as client and connect to an AP

Read this tutorial first: Access point and client.

1 . Configure wlan0 in apuV4 as AP.
You need to set

for hostapd, because currently the openwifi NIC sdr0 supports only OFDM. Use hostapd /root/hostapd.conf -dd to see more debug information.

2 . operate openwifi NIC sdr0 in zc706.

Run: iwlist sdr0 scan

You should see AP information like:

Cell 01 - Address: 04:F0:21:11:E5:55
          Frequency:5.18 GHz (Channel 36)
          Quality=41/70  Signal level=-69 dBm
          Encryption key:off
          Bit Rates:6 Mb/s; 9 Mb/s; 12 Mb/s; 18 Mb/s; 24 Mb/s
                    36 Mb/s; 48 Mb/s; 54 Mb/s
          Extra: Last beacon: 10ms ago
          IE: Unknown: 000769706572664150
          IE: Unknown: 01088C129824B048606C
          IE: Unknown: 030124
          IE: Unknown: 7F080000000000000040
          IE: Unknown: AF00


iwconfig sdr0 mode managed
iwconfig sdr0 essid iperfAP
ifconfig sdr0 up

Experiment 2: openwifi communicate with commercial wifi card in ad-hoc mode

You need a commercial wifi card that support IBSS mode. To check the wifi card capability (mode, rate, etc), you can use iw list command. Please make sure they have Wi-Fi card AR9462 or AR93xx. Please avoid nodes with Wi-Fi card AR928X (ZOTAC) , QCA988x or QCA986x/988x (APU).

1 . Start ad-hoc mode of DSS node, for example dssK5 or dssJ5 :

($xxx means a parameter you should specify. The ad-hoc network SSID will be "ad-hoc-test")
($nic_name, the network interface name when you run ifconfig)
($ch_number, Wi-Fi channel number, such as 1, 6, 11)
($ip_addr, IP address you want)

sudo ip link set $nic_name down
sudo iwconfig $nic_name mode ad-hoc
sudo iwconfig $nic_name essid 'ad-hoc-test'
sudo ip link set $nic_name up
sudo iwconfig $nic_name channel $ch_number
sudo ifconfig $nic_name $ip_addr netmask
iwconfig $nic_name

(Now you should see … ESSID “ad-hoc-test” … Cell: xx:yy:zz…)

2 . Start ad-hoc mode of node 2 (openwifi or ZOTAC), and let it to join the “ad-hoc-test” network:

($cell should be xx:yy:zz... you saw in node 1)
sudo ip link set $nic_name down
sudo iwconfig $nic_name mode ad-hoc
sudo iwconfig $nic_name essid 'ad-hoc-test'
sudo ip link set $nic_name up
sudo iwconfig $nic_name channel $ch_number
sudo iwconfig $nic_name ap $cell
sudo ifconfig $nic_name $ip_addr netmask
iwconfig $nic_name

Advanced topics

Restore rootfs if SD card is corrupted

Follow instructions below if there is no usable rootfs, or if BOOT.BIN is not found

  1. Download a recent openwifi image file from this link, make sure you extract the file and get an image file with .img extension, will refer to it as openwifi-xxxx.img in this tutorial.
  2. The first steps (up till step 6) are the same as the normal procedure explained in the section Boot Linux.
  3. The 7th step is replaced by source xsdb_dow_bs_fsbl.tcl, after this step, execute con, interrupt uboot auto start process, and execute bootm 0x3000000 0x2000000 0x2a00000 in the serial console, this will launch linux from the ramdisk.
  4. After linux is booted, in the serial console, give the eth0 an IP address by executing ifconfig eth0
  5. Configure your host IP accordingly by executing ifconfig eno2, eno2 can also be eth2, make sure you can ssh to the zynq board using user name root and password root.
  6. In the host, go to the directory where you store the SD card image and execute the following command, this command will take more than half an hour, so be patient.
dd bs=4M if=openwifi-xxxx.img | ssh root@ dd of=/dev/mmcblk0
  1. Wait until the command completes, and then on the zynq board, execute in the serial console: mkdir /sdcard ; mount /dev/mmcblk0p1 /sdcard/ ; cp /sdcard/zc706_fmcs2/BOOT.BIN /sdcard ; cp /sdcard/zc706_fmcs2/devicetree.dtb /sdcard ; umount /sdcard ; poweroff, after that reboot the zc706 board in jFed, wait 10 second, and use the normal procedure to launch Linux.

SDR TX time slicing

For SDR TX, there is a hardware/FPGA timer based slicing mechanism.

Example of two time slices (2:98 allocation) for explanation:

  • In FPGA, a timer counts from 0 to 50000us again and again.
  • When timer value is between 1000us~50000us, we do tx for slice0 if there are any packets left in the FPGA slice0 queue. (Linux driver receives packets from Linux upper layer, and put packets in FPGA hardware queue. Depending on the target MAC address and type of the packet, driver knows that the packet should be put into FPGA slice0 queue or slice1 queue).
  • For slice1, same procedure except that timer value has to be between 0~1000us. So 0~1000us means 2% (1000/50000) air time of SDR tx, 1000~50000 means 98% (49000/50000) air time of SDR tx.

We only do above slicing operation for unicast data packet. For 802.11 management/control packet or broadcasting packet, we will send immediately, because they don’t belong to any slice and they are important for the whole Wi-Fi network.

Note that all above numbers (10000us, 50000us, etc) are configurable. The minimum time unit is 1us.

Slice config command:

# set SDR tx slice0 target MAC address (assume it is 6c:fd:b9:4c:b1:c1)
     ./sdrctl dev sdr0 set addr0 b94cb1c1
# set SDR tx slice0 cycle length in us
     ./sdrctl dev sdr0 set slice_total0 49999
     # set SDR tx slice0 start time in us
     ./sdrctl dev sdr0 set slice_start0 1000
     # set SDR tx slice0 end time in us
     ./sdrctl dev sdr0 set slice_end0  49999

To set for slice1, just replace those “0” to “1”.

To get value of above configurations, just replace “set” to “get”