In my ongoing series focusing on the Zynqberry, I've returned to my Pi OS that I've been developing using PetaLinux 2019.2 to make the Zynqberry interchangeable with a Raspberry Pi running the standard wheezy image. Previously, I added Python, CircuitPython, and internet connectivity via the Ethernet port to my Pi OS. The next major feature of the Raspberry Pi the Zynqberry needs is wireless support.
For Raspberry Pis that don't have Wi-Fi chips onboard, USB Wi-Fi adapters are available like this one from Adafruit.
This particular Wi-Fi module is built on the Realtek Semiconductor RTL8192CU 802.11n WLAN Adapter, which after looking up it, seems to be one of the most common chipsets for USB Wi-Fi adapters.
To add the compatibility in my PetaLinux project for Pi OS to support RTL8192CU chipset USB Wi-Fi adapters the kernel, root filesystem, and device tree all needed to be modified/updated.
Update kernelStarting with the kernel of the Pi OS embedded Linux image, entering the kernel configuration editor:
petalinux-config -c kernel
To determine what kernel drivers needed, I've been using linux-hardware.org to search product/chip names
This particular Wi-Fi module is built on the Realtek Semiconductor RTL8192CU 802.11n WLAN Adapter, which after looking up it on linux-hardware.org tells me that I need to enable the following drivers in the kernel (using the PetaLinux kernel configuration editor GUI in this case):
CONFIG_WLAN
CONFIG_RTLWIFI
CONFIG_RTL8192CU
To support these kernel options as well as wireless functionality in general, I also enabled [*] the following kernel driver packages:
CONFIG_USB
CONFIG_RFKILL
CONFIG_MAC80211
CONFIG_RTL_CARDS
CONFIG_NETDEVICES
CONFIG_CFG80211_WEXT
CONFIG_WLAN_VENDOR_REALTEK
CONFIG_MAC80211_RC_MINSTREL
CONFIG_MAC80211_RC_MINSTREL_HT
CONFIG_USB_GADGET_VBUS_DRAW 500
CONFIG_MAC80211_RC_DEFAULT_MINSTREL
Just like I found in a past project using a USB webcam with the MiniZed, the Maximum VBUS Power usage was set to limit the USB port to provide no more than 2mA. USB Wi-FI adapters can draw anywhere from 100mA - 500mA, averaging around 200mA. I went ahead and set it to the max of 500mA. If a USB Wi-FI adapter needs 500mA or more, it needs to be plugged into a powered USB hub instead of directly into the Zynqberry.
The Realtek wireless chips also need to have firmware files programmed onto them at runtime. To achieve this, the CONFIG_EXTRA_FIRMWARE kernel option is a string that takes space delimited names of the firmware binary files to be loaded onto a given peripheral. The firmware file names are the same names that appear in MODULE_FIRMWARE() and request_firmware() in the source code.
These files live in the directory specified by the CONFIG_EXTRA_FIRMWARE_DIR kernel option, which controls the directory in which the kernel build system looks for the firmware files listed in the CONFIG_EXTRA_FIRMWARE option. CONFIG_EXTRA_FIRMWARE_DIR is /lib/firmware by default, but I still entered it explicitly since the option is blank in the configuration editor.
The RTL8192cu chipset has four possible firmware binary files:
- rtl8192cufw.bin
- rtl8192cufw_A.bin
- rtl8192cufw_B.bin
- rtl8192cufw_TMSC.bin
Since the source code for the linux firmware driver creates the rtlwifi directory to place all of the firmware binaries into, it must be included in the filename entered in the CONFIG_EXTRA_FIRMWARE field:
rtlwifi/rtl8192cufw.bin rtlwifi/rtl8192cufw_A.bin rtlwifi/rtl8192cufw_B.bin rtlwifi/rtl8192cufw_TMSC.bin
After enabling the appropriate options in the kernel configuration editor, exit the editor and elect to save the new configuration.
Since the Realtek firmware is part of the non-free Linux archive, it's not enabled in as an option in a PetaLinux project by default. The Realtek firmware is a part of the linux-firmware repository that's available in the open-embedded core of PetaLinux. To add the firmware to the embedded Linux image build of the PetaLinux project, open petalinuxbsp.conf in the <project dir>/project-spec/meta-user/conf directory and add the following line:
IMAGE_INSTALL_append = "linux-firmware-rtl8192cu"
Update Root FilesystemMoving on to the root filesystem configuration editor:
petalinux-config -c rootfs
The Pi OS image needs a few packages added for handling wireless functions such as wpa_supplicant and iptables. I also added other all-around handy packages such as BusyBox, CoreUtils, and build-essential.
CONFIG_wget
CONFIG_busybox
CONFIG_coreutils
CONFIG_opkg
CONFig_libopkg
CONFIG_opkg-utils
CONFIG_iptables
CONFIG_wpa-supplicant
CONFIG_wpa-supplicant-cli
CONFIG_packagegroup-core-buildessential
Update Device TreeFinally the device tree in the Pi OS project needs to have the wlan0 alias tied to the USB PHY device node:
/include/ "system-conf.dtsi"
/ {
aliases{
// eth0 = &usb0;
wlan0 = &usb0;
spi0 = &qspi;
spi1 = &spi1;
};
};
After saving and closing the device tree file, build the PetaLinux project:
petalinux-build
Then repackage a new boot binary for the Zynqberry:
petalinux-package --boot --fsbl ./images/linux/zynq_fsbl.elf --fpga ./images/linux/system.bit --u-boot ./images/linux/u-boot.elf --force
Update the SD CardStarting with the SD Card with the old Pi OS image on it, plug it into the host PC and mount the two partitions to directories in /media/ (which is /media/BOOT/ and /media/rootfs/in my case).
sudo mount /dev/sdc1 /media/BOOT/
sudo mount /dev/sdc2 /media/rootfs/
Remove the old Pi OS image files and replace them with the new:
sudo rm -rfv /media/BOOT/
sudo rm -rfv /media/rootfs/
sudo tar -xvf ./images/linux/rootfs.tar.gz -C /media/rootfs/
sync
sudo cp ./images/linux/BOOT.BIN /media/BOOT/
sudo cp ./images/linux/image.ub /media/BOOT/
sudo cp ./images/linux/system.dtb /media/BOOT/
sync
I strongly recommend using the sync command between mass read/writes onto an SD card as I have done above. Sometimes the OS of the host PC is still holding on to the SD card resources in the background and I've had it corrupt the embedded Linux image on the SD card in the past.
After making sure the files are synced, unmount each partition of the SD card from the host PC:
sudo umount /media/BOOT/
sudo umount /media/rootfs/
The QSPI flash memory of the Zynqberry needs the new boot binary image programmed into it. This can be done in Vitis using the Program Flash Memory under the Xilinx tab of the toolbar:
The boot binary and Zynq first stage bootloader output by the Pi OS PetaLinux project are found in the <project directory>/images/linux directory. Be sure the Flash Type is set to qspi-x4-single and I strongly recommend always checking the Verify after flash option.
Boot Zynqberry & Plug in USB WiFi AdapterAfter flashing the QSPI and installing the SD card back into the slot on the Zynqberry, plug in the USB Wi-Fi adapter and the power/UART cable from the host PC.
Connect to the serial port created by the Zynqberry with an application like Putty or TeraTerm to watch the boot sequence:
I spent more time than I'd like to admit trying to figure out why/what was causing the rtl8192c_common: chksum report fail! REG_MCUFWDL:0x00030000. and rtl8192c_common: Firmware is not ready to run! error messages. However I eventually gave up after I couldn't find any issues with the Wi-Fi adapter's functionality and it was working normally.
Connect to a Wi-Fi NetworkOn the first boot of the Zynqberry, the wpa_supplicant.conf file is not configured to join any specific network, so use a text editor to add the network's ESSID and password the Zynqberry is to be connected to.
root@pi_os:~# vi /etc/wpa_supplicant.conf
The key management type also needs to be specified for the specified network in wpa_supplicant.conf.
ctrl_interface=/var/run/wpa_supplicant
ctrl_interface_group=0
update_config=1
network={
key_mgmt=WPA-PSK
ssid="<your wi-fi network name>"
psk="<your wi-fi password>"
}
The wireless interface also needs to be added to the /etc/network/interfaces file:
root@pi_os:~# vi /etc/network/interfaces
Here the wlan0 interface is linked to the appropriate driver, WPA configuration file (wpa_supplicant.conf), set to use DHCP, and configured to be brought up at every boot (auto wlan0).
auto lo
iface lo inet loopback
# Static IP example
#auto eth0
#iface eth0 inet static
# address 192.168.1.19
# netmask 255.255.255.0
# network 192.168.1.0
# gateway 192.168.1.1
# DHCP Example
auto eth0
iface eth0 inet dhcp
# Wireless interface
auto wlan0
iface wlan0 inet dhcp
wireless_mode managed
wireless_essid any
wpa-driver wext
wpa-conf /etc/wpa_supplicant.conf
# Second NIC (if any)
#auto eth1
#iface eth1 inet dhcp
Once the wireless interfaces is appropriately configured, start wpa_supplicant:
root@pi_os:~# wpa_supplicant -Dnl80211 -iwlan0 -c/etc/wpa_supplicant.conf -B
To test the connection, I first pinged my router on the local network (192.168.1.1) and then pinged google.com to verify internet connection.
The Zynqberry has always been one of my favorite FPGA development boards as it was one of my first that I got started with. Adding wireless capability with this version of Pi OS will keep it as a strong tool in my lab.
Comments