This project provides instructions to help you quickly get up and running with adding a combination WiFi & Bluetooth module and NVMe SSD on the M.2 HSIO add-on module for the ZUBoard.
PrerequisitesA few things to do to install an OS image before we get to have fun with the hardware.
- Download the Linux OS image for the ZUBoard.http://avnet.me/m2-hsio-linux-test(md5sum = b80da13b2c58d3b4088829e555ff8b84)
- Extract the OS image from the downloaded zip archive. Write the Linux OS image to a microSD card. Eject the microSD card when the extraction is completed.
$ cd <PATH_TO_DOWNLOADED_FILE>/
$ unzip ./zub1cg_sbc_m2_test_2022_2.zip
$ sudo dd if=./zub1cg_sbc_m2_test_2022_2.img of=/dev/sd<x> bs=1M conv=fsync status=progress
$ sync && sync
Assemble The Hardware- Install the Azurewave WiFi/Bluetooth module on the M.2 HSIO board in the “KEY-E” M.2 connector (J15). Use a rubber band or fit a M2.0 x 2.5mm screw to hold the end of the board down to the mounting standoff (MH7).
- Install the NVMe SSD on the M.2 HSIO board in the “KEY-B” M.2 connector (J16). Use a rubber band or fit a M2.0 x 2.5mm screw to hold the end of the board down to the mounting standoff (MH9).
- Install a jumper on the J19 header on the M.2 HSIO board.
- Install the assembled Avnet M.2 HSIO module on the ZUBoard-1CG into the High Speed I/O Connector (J2).
- Insert the USB UART and USB-C power cables to the ZUBoard-1CG board as follows.
- Attach the micro USB cable to the USB-UART port (J16) on the ZUBoard-1CG board and to an available USB port on the test PC.
- Connect the USB-C power cable to the power connector (J15). The VIN (D22), voltage indicator (D14-D16), and EN_SINK (D17) LEDs should be illuminated.
- The Ethernet cable (yellow cable in the photo above) is not required
- Set the boot mode switches on the ZUBoard to SD card mode. (SW1-4; 0x5; off-on-off-on).
- Insert the microSD card into microSD card cage (J12) on the ZUBoard.
- Press the power switch (SW7) to boot the board.
- Open a serial console on your host PC for the UART COM port connected to the ZUBoard (GTKTerm, minicom, TeraTerm, etc.) with UART settings: Baud: 115, 200; Parity: None; Bits: 8; Stop bits: 1; Flow control: None
- Observe the Terminal program window displaying boot data. Do not press any buttons during boot! The ZUBoard-1CG has completed booting when one of the red LEDs (D9) will be flashing and the serial port terminal window will display the Linux login prompt. Log into the Linux OS (login = root). There is no password.
- Turn off Linux kernel messages being sent to stdout (the UART console).
# dmesg -n 1
- Load the WiFi / Bluetooth device driver.
# modprobe moal mod_para=nxp/wifi_mod_para.conf
- Bring up the WiFi interface. The device name for the Azurewave module is 'mlan0'.
# ifup mlan0
- Enable the WiFi interface. You may see a message that WiFi is already enabled. You can ignore this message.
# connmanctl enable wifi
- Scan for WiFi access points.
# connmanctl scan wifi
- Display the found WiFi networks. In this case the name of the WiFi WLAN (the SSID) is 'WiFi_test_AP'.
# connmanctl services | grep WiFi_test_AP
- The Azurewave WiFi module provides different WLAN interfaces for different functions (mlan0, uap0, and wfd0). The name of the interface is structured as follows: wifi_<MAC ID>_<hashed value>_<managed | unmanaged>_<security type>We want the second interface in the list, which corresponds to the 'D8:C0:A6:0F:D7:8F' MAC ID and 'mlan0' interface.
- Copy the network name to the clipboard so we don't have to type it all out later.
- Connect to the WiFi network (paste the network name from the previous command). NOTE: In this example the 'WiFi_test_AP' WiFi network is not configured for any password security. This is obviously not usual or recommended, but makes documenting WiFi use for this tutorial much simpler.
# connmanctl connect wifi_d8c0a60fd78f_576946695f746573745f4150_managed_none
- Send a few ping requests to the WiFi access point. For this example the WiFi AP has an IP address of 192.168.2.1.
# ping -c 5 -I mlan0 192.168.2.1
- The WiFi AP for this example is also running a iperf server, so we can run a quick test to send some data packets to verify the WiFi interface is working and benchmark the WiFi throughput. Run the 'iperf' test to connect to the WiFi AP (IP address 192.168.2.1), update every 2 seconds, and run for a total of 10 seconds.
# iperf -c 192.168.2.1 -i 2 -t 10
- In case you needed to start over or skipped the WiFi Instructions, start by turning off Linux kernel messages being sent to stdout (the UART console).
# dmesg -n 1
- Has the device driver been loaded already? Check first. Run the 'lsmod' command and check that the 'moal' driver is already loaded. In this case we see the driver is already loaded, so we don't need to do it again.
- If you haven't already loaded the device driver, do it now.
# modprobe moal mod_para=nxp/wifi_mod_para.conf
- Bring up the Bluetooth host controller interface. In this example the ZynqMP PS UART used for Bluetooth is 'ttyPS1' and we want a 115200 baud rate.
# hciattach /dev/ttyPS1 any 115200 flow
- Unblock all RF interfaces.
# rfkill unblock all
- Bring up the Bluetooth interface.
# hciconfig hci0 up
- Find and show the Bluetooth controller, Note that the controller refers to the MAC ID for the Bluetooth interface and will be different for your Bluetooth module.
# bluetoothctl show
- Start a 'bluetoothctl' shell.
# bluetoothctl
- Scan for nearby devices.
[bluetooth]# scan on
- Pick a device to pair with. In this case 'Tom's S24 Ultra' (MAC ID 80:07:94:3A:02:06). The device to be paired with needs to be visible to the ZUBoard. Check the device Bluetooth settings to verify this.
[bluetooth]# pair 80:07:94:3A:02:06
- That's it! We have verified the Bluetooth interface is working and can pair with another device. Before moving on it is a good idea to exit the 'bluetoothctl' shell and kill the 'hciattach' Linux process.
[bluetooth]# exit
# PID=$(ps -L | grep hciattach | awk '{print $2}') && kill -9 $PID
- Verify the NVMe SSD storage on the M.2 HSIO board is recognized in Linux. The device node for the SSD should be identified as 'nvme0'.
# ls -al /dev | grep nvme
- If the SSD you are using is new it is probably not partitioned or formatted. The following steps will perform these tasks to create a single EXT4 filesystem partition on a 128 GB Delkin NVMe SSD. If you are using a SSD that you know is already partitioned and formatted, and you don't want to make any changes, then you can skip the next steps. NOTE: BE VERY CAREFUL with the following commands and be certain there is no valuable data on the SSD. Creating a new partition and formatting the SSD will destroy all data on the drive. Start by listing the available disk devices by using the 'fdisk' command. In this example the NVMe SSD is identified as '/dev/nvme0n1'.
# fdisk -l | grep nvme
- Use the 'fdisk' utility on the SSD to create, delete, and modify the partitions on the SSD.
# fdisk /dev/nvme0n1
- At the 'fdisk' prompt type 'n' to create a new partition. Accept the defaults for 'p' primary partition on the device, partition number '1', beginning sector, and last sector. The beginning and end sectors may be different for your particular SSD. In this example the partition fills the entire SSD with a formatted capacity of 119.2 GB.
- Use the 'w' command to write the partition changes to the partition table on the SSD and exit 'fdisk'.
- The new partition is created, but is not ready to use yet. It must be formatted first. Use the 'mkfs.ext4' command to format the new partition with the Linux EXT4 file system. Notice now that the device name has changed to '/dev/nvme0n1p1' to indicate the partition 'p1' we just created.
# mkfs.ext4 /dev/nvme0n1p1
- That is it! We just created and formatted a new partition on the NVMe SSD. Reboot the board to verify that Linux identifies and mounts the new partition at boot time. After rebooting, Linux should identify the 'nvme0n1p1' partition and mount it on the '/run/media/nvme0n1p1' folder.
# cat /proc/mounts |grep nvme
- Now let's see how well it performs to write and read a file.
Test the performance of files reads and writes for the NVMe storage on the M.2 HSIO module. This webpage provides a great description of a good way to evaluate the file read and write performance using common Linux utilities.
- Write a 1 GB test file
The Linux 'dd'utility is great for quickly and easily creating and duplicating a file. In order to best test the performance of a file write it is important that the file is at least as large as the RAM in the system in order to avoid the whole file being cached in memory. For the ZUBoard this means a 1GB file. Running the 'dd' command in a timed shell ensures the full file is written to the SSD before the shell exits. The 'sync' command forces the process to write the entire file to disk before completing. Change directories to where the SSD is mounted (/run/media/nvme0n1p1) and execute the following 'dd' command to write a file of 256K blocks of size 4K (256K * 4K = 1GB).
# cd /run/media/nvme0n1p1
# time sh -c "dd if=/dev/zero of=./test.tmp bs=4k count=256K && sync"
Now, let’s do the math. The 'dd' command tells us how many bytes were written, and the 'time' command tells us how long it took.
Use the real time measurement at the bottom of the output.
Convert bytes to MB to make more sensible numbers.
Bytes converted to MB / "real" time seconds (1073741824/ 1024 / 1024) / (5.748)
This gives us an average of 178MB per second over the duration of the test to completely write the file to disk.
- Read a 1 GB test file
Before testing the file read it is important to first write a dummy file to disk. This will flush the file cache and force the file read to fetch the complete file from disk. Otherwise a portion of the file we just wrote may still be left in RAM and this would skew the read performance test result.
Create a file using 'dd'which is about the same size as the RAM installed on the system. The below assumes 1GB of RAM is installed. You can check how much RAM is installed with the Linux 'free' command.
# free
# dd if=/dev/zero of=./clearcache.tmp bs=4k count=256K
# time sh -c "dd if=./test.tmp of=/dev/null bs=4K"
Use the same math as we did for the 'dd' file write.
Convert bytes to MB to make more sensible numbers.
Bytes converted to MB / "real" time seconds. (1073741824/ 1024 / 1024) / (3.692)
This gives us an average of 277 MB per second over the duration of the test.
Experiment with changing the 'dd' block size (bs=<xx>) and loop (count=<xx>) arguments to see how this affects NVMe disk performance. Changing the block size will for sure influence disk performance in ways that may surprise you. Users don't generally have an influence on the block size the Linux OS uses to copy and create files so this exercise is largely academic, but the results are still interesting to see and it gives us a good idea of our NVMe disk performance.
ConclusionI hope these instructions were helpful for you to be successful with the Avnet M.2 HSIO add-on module for the ZUBoard. The combination of WiFi, Bluetooth, and PCIe (NVMe SSD) storage on the M.2 HSIO module with the compute power and I/O expansion of the ZUBoard opens up many compelling use cases. What will yours be?
Revision History2024/03/15: First version
Comments
Please log in or sign up to comment.