
A Step-by-Step Guide to Integrating AX210NGW Wi-Fi 6E With OK3576-C Development Board
In the era of ubiquitous connectivity, wireless communication technology is an essential part of embedded systems. Wi-Fi modules, as a crucial link between devices and networks, require high performance and compatibility. Intel's AX210NGW Wi-Fi 6E module, a high-performance wireless network adapter, supports the latest Wi-Fi 6E standard and Bluetooth 5.3, offering excellent transmission speeds and compatibility, thus providing strong support for wireless connectivity in embedded systems.
AX210NGW Wi-Fi 6E Module
To meet the demand for high-performance embedded control applications, this article details how to adapt the AX210NGW Wi-Fi 6E module (hereinafter “the module”) on the Forlinx Embedded OK3576-C development board, enabling developers to quickly start and utilize its performance advantages.
Note: The Bluetooth function of the Wi-Fi module has not been adapted. This article only covers Wi-Fi adaptation.
OK3576-C Development Board Interface Diagram
First, Wi-Fi module should be connected to the Forlinx OK3576-C development board. The Wi-Fi module uses an M.2 Key A + E interface, while the OK3576-C board lacks this interface. An M.2 to PCIe dual-band wireless network card adapter can be used for conversion.
Go to the kernel directory to start configuration:
forlinx@ubuntu20:~/3576$ cd kernel-6.1/ forlinx@ubuntu20:~/3576/kernel-6.1$ make menuconfig ARCH=arm64
Select in the following order:
Location: -> Device Drivers -> Network device support (NETDEVICES [=y]) -> Wireless LAN (WLAN [=y]) -> Intel devices (WLAN_VENDOR_INTEL [=y]) -> Intel Wireless WiFi Next Gen AGN-Wireless-N/Advanced-N/Ultimate-N (iwlwifi) (IWLWIFI [=m]) -> Intel Wireless WiFi MVM Firmware support (IWLMVM [=m])
Start to compile:
forlinx@ubuntu20:~/3576/kernel-6.1$ export CROSS_COMPILE=/home/forlinx/3576/prebuilts/gcc/linux-x86/aarch64/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu- forlinx@ubuntu20:~/3576/kernel-6.1$ export PATH=$PATH:/home/forlinx/3576/prebuilts/gcc/linux-x86/aarch64/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/ forlinx@ubuntu20:~/3576/kernel-6.1$ make ARCH=arm64 rk3576-evb1-v10-linux.img
Finally, copy the compiled module to the OK3576-C development board. Here, copy the module to the/root directory. Enter the kernel source path:
(1) drivers/net/wireless/intel/iwlwifi/iwlwifi.ko
(2) drivers/net/wireless/intel/iwlwifi/mvm/iwlmvm.ko
In addition, copy the Wi-Fi firmware and STA scripts to the/root directory for backup.
root@rk3576-buildroot:/root# ls firmware.zip fltest_wifi.sh iwlmvm.ko iwlwifi.ko
STA scripts can refer to the following contents, such as creating scripts by yourself, and remember to add executable permissions.
#!/bin/sh cnt1=`ps aux | grep hostapd | grep -v grep | wc -l` if [ "$cnt1" != "0" ];then killall hostapd > /dev/null fi ifconfig uap0 down function usage() { echo "Usage: -i-s-p" echo "eg: ./wifi.sh -i mlan0 -s bjforlinx -p 12345678 " echo "eg: ./wifi.sh -i mlan0 -s bjforlinx -p NONE " echo " -i : mlan0 or mlan1" echo " -s : wifi ssid" echo " -p : wifi password or NONE" } function parse_args() { while true; do case "$1" in -i ) wifi=$2;echo wifi $wifi;shift 2 ;; -s ) ssid=$2;echo ssid $ssid;shift 2 ;; -p ) pasw=$2;echo pasw $pasw;shift 2 ;; -h ) usage; exit 1 ;; * ) break ;; esac done } if [ $# != 6 ] then usage; exit 1; fi parse_args $@ if [ -e /etc/wpa_supplicant.conf ] then rm /etc/wpa_supplicant.conf fi echo \#PSK/TKIP >> /etc/wpa_supplicant.conf echo ctrl_interface=/var/run/wpa_supplicant >>/etc/wpa_supplicant.conf echo ctrl_interface_group=0 >>/etc/wpa_supplicant.conf echo update_config=1 >>/etc/wpa_supplicant.conf echo network={ >>/etc/wpa_supplicant.conf echo ssid=\"$ssid\" >>/etc/wpa_supplicant.conf echo scan_ssid=1 >>/etc/wpa_supplicant.conf if [ $pasw == NONE ] then echo key_mgmt=NONE >>/etc/wpa_supplicant.conf else echo psk=\"$pasw\" >>/etc/wpa_supplicant.conf echo key_mgmt=WPA-EAP WPA-PSK IEEE8021X NONE >>/etc/wpa_supplicant.conf # echo group=CCMP TKIP WEP104 WEP40 >>/etc/wpa_supplicant.conf fi echo } >>/etc/wpa_supplicant.conf ifconfig -a|grep mlan0 |grep -v grep > /dev/null if [ $? -eq 0 ] then ifconfig mlan0 down > /dev/null fi ifconfig -a|grep mlan1 |grep -v grep > /dev/null if [ $? -eq 0 ] then ifconfig mlan1 down > /dev/null fi ifconfig -a|grep eth0 |grep -v grep > /dev/null if [ $? -eq 0 ] then ifconfig eth0 down > /dev/null fi ifconfig -a|grep eth1 |grep -v grep > /dev/null if [ $? -eq 0 ] then ifconfig eth1 down > /dev/null fi ifconfig -a|grep usb0 |grep -v grep > /dev/null if [ $? -eq 0 ] then ifconfig usb0 down > /dev/null fi ps -fe|grep wpa_supplicant |grep -v grep > /dev/null if [ $? -eq 0 ] then kill -9 $(pidof wpa_supplicant) fi sleep 1 ifconfig $wifi up > /dev/null sleep 1 (wpa_supplicant -Dnl80211,wext -i$wifi -c/etc/wpa_supplicant.conf >/dev/null) & echo "waiting..." sleep 3 wpa_cli -i$wifi status |grep COMPLETED |grep -v grep >/dev/null if [ $? -eq 0 ] then dhcpcd -i $wifi echo "Finshed!" else echo "try to connect again..." sleep 3 wpa_cli -i$wifi status |grep COMPLETED |grep -v grep >/dev/null if [ $? -eq 0 ] then dhcpcd -i $wifi echo "nameserver 114.114.114.114" > /etc/resolv.conf echo "Finshed!" else echo "************************************************" echo "connect faild,please check the passward and ssid" kill -9 $(pidof wpa_supplicant) exit 1 fi fi
Next, the firmware needs to be deployed to the /lib/firmware path of the board.
root@rk3576-buildroot:/root# unzip firmware.zip -d /lib/ root@rk3576-buildroot:/root# ls /lib/firmware/iwlwifi-ty-a0-gf-a0* /lib/firmware/iwlwifi-ty-a0-gf-a0-59.ucode /lib/firmware/iwlwifi-ty-a0-gf-a0-66.ucode /lib/firmware/iwlwifi-ty-a0-gf-a0-71.ucode /lib/firmware/iwlwifi-ty-a0-gf-a0-72.ucode /lib/firmware/iwlwifi-ty-a0-gf-a0-73.ucode /lib/firmware/iwlwifi-ty-a0-gf-a0-74.ucode /lib/firmware/iwlwifi-ty-a0-gf-a0-77.ucode /lib/firmware/iwlwifi-ty-a0-gf-a0-78.ucode /lib/firmware/iwlwifi-ty-a0-gf-a0-79.ucode /lib/firmware/iwlwifi-ty-a0-gf-a0-81.ucode /lib/firmware/iwlwifi-ty-a0-gf-a0-83.ucode /lib/firmware/iwlwifi-ty-a0-gf-a0-84.ucode /lib/firmware/iwlwifi-ty-a0-gf-a0-86.ucode /lib/firmware/iwlwifi-ty-a0-gf-a0-89.ucode /lib/firmware/iwlwifi-ty-a0-gf-a0.pnvm
Next, load the module:
root@rk3576-buildroot:/root# insmod iwlwifi.ko [ 1996.796387] Intel(R) Wireless WiFi driver for Linux [ 1996.803930] iwlwifi 0000:01:00.0: api flags index 2 larger than supported by driver [ 1996.804075] iwlwifi 0000:01:00.0: TLV_FW_FSEQ_VERSION: FSEQ Version: 0.0.2.36 [ 1996.806470] iwlwifi 0000:01:00.0: loaded firmware version 72.a764baac.0 ty-a0-gf-a0-72.ucode op_mode iwlmvm root@rk3576-buildroot:/root# insmod iwlmvm.ko [ 2005.034727] iwlwifi 0000:01:00.0: Detected Intel(R) Wi-Fi 6 AX210 160MHz, REV=0x420 [ 2005.036391] thermal thermal_zone6: power_allocator: sustainable_power will be estimated [ 2005.036966] thermal thermal_zone6: failed to read out thermal zone (-61) [ 2005.212436] iwlwifi 0000:01:00.0: loaded PNVM version 35148b80 [ 2005.228063] iwlwifi 0000:01:00.0: Detected RF GF, rfid=0x10d000 [ 2005.299203] iwlwifi 0000:01:00.0: base HW address: 4c:49:6c:f0:99:7a [ 2005.323434] iwlwifi 0000:01:00.0 wlp1s0: renamed from wlan0
If there is the above information, it indicates that the module has been loaded successfully, and the network card node information can be seen:
root@rk3576-buildroot:/root# ifconfig wlp1s0 wlp1s0 Link encap:Ethernet HWaddr 4C:49:6C:F0:99:7A BROADCAST MULTICAST MTU:1500 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:1000 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
Let's start testing the STA mode:
root@rk3576-buildroot:/root# ./fltest_wifi.sh -i wlp1s0 -s forlinx-wlan -p fl03123102650 ifconfig: SIOCGIFFLAGS: No such device wifi wlp1s0 ssid forlinx-wlan pasw fl03123102650 [ 2242.183049] rk_gmac-dwmac 2a220000.ethernet eth0: FPE workqueue stop waiting... try to connect again... [ 2247.876030] wlp1s0: authenticate with ee:b9:70:81:7d:88 [ 2247.883905] wlp1s0: send auth to ee:b9:70:81:7d:88 (try 1/3) [ 2248.015556] wlp1s0: send auth to ee:b9:70:81:7d:88 (try 2/3) [ 2248.119667] wlp1s0: send auth to ee:b9:70:81:7d:88 (try 3/3) [ 2248.172500] wlp1s0: authenticated [ 2248.175429] wlp1s0: associate with ee:b9:70:81:7d:88 (try 1/3) [ 2248.183347] wlp1s0: RX AssocResp from ee:b9:70:81:7d:88 (capab=0x1931 status=0 aid=42) [ 2248.192191] wlp1s0: associated [ 2248.218419] IPv6: ADDRCONF(NETDEV_CHANGE): wlp1s0: link becomes ready main: control_open: Connection refused dhcpcd-10.0.4 starting dev: loaded udev DUID 00:01:00:01:c7:92:c8:aa:4c:49:6c:f0:99:7a wlp1s0: connected to Access Point: forlinx-wlan wlp1s0: IAID 6c:f0:99:7a wlp1s0: soliciting an IPv6 router wlp1s0: rebinding lease of 192.168.81.206 wlp1s0: NAK: from 192.168.80.1 wlp1s0: soliciting a DHCP lease wlp1s0: offered 192.168.81.206 from 192.168.80.1 wlp1s0: probing address 192.168.81.206/23 wlp1s0: leased 192.168.81.206 for 28800 seconds wlp1s0: adding route to 192.168.80.0/23 wlp1s0: adding default route via 192.168.80.1 forked to background, child pid 1185 dhcpcd_fork_cb: truncated read 0 (expected 4) Finshed!
Test ping to the embedded official website of Forlinx to check whether the Internet can be accessed normally:
root@rk3576-buildroot:/root# ifconfig wlp1s0 wlp1s0 Link encap:Ethernet HWaddr 4C:49:6C:F0:99:7A inet addr:192.168.81.206 Bcast:192.168.81.255 Mask:255.255.254.0 inet6 addr: fe80::4e49:6cff:fef0:997a/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:1547 errors:0 dropped:93 overruns:0 frame:0 TX packets:21 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:150462 (146.9 KiB) TX bytes:3123 (3.0 KiB) root@rk3576-buildroot:/root# ping www.forlinx.com PING s-526319.gotocdn.com (211.149.226.120) 56(84) bytes of data. 64 bytes from 211.149.226.120 (211.149.226.120): icmp_seq=1 ttl=54 time=45.9 ms 64 bytes from 211.149.226.120 (211.149.226.120): icmp_seq=2 ttl=54 time=40.1 ms 64 bytes from 211.149.226.120 (211.149.226.120): icmp_seq=3 ttl=54 time=39.8 ms 64 bytes from 211.149.226.120 (211.149.226.120): icmp_seq=4 ttl=54 time=40.8 ms 64 bytes from 211.149.226.120 (211.149.226.120): icmp_seq=5 ttl=54 time=40.5 ms ^C --- s-526319.gotocdn.com ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 4007ms rtt min/avg/max/mdev = 39.813/41.401/45.867/2.257 m
Pinging the Forlinx official website confirms normal functionality, indicating successful STA mode configuration.
To enable AP mode, follow these steps: Next, let's look at how to configure AP mode.
The first step is to write the AP mode script. The script is placed in the/usr/bin/directory, and the file name is fltest _ hostapd. sh, which also needs to be configured with executable permissions.
#!/bin/sh cnt=`ps aux | grep wpa_supplicant | grep -v grep | wc -l` if [ "${cnt}" != "0" ];then killall wpa_supplicant > /dev/null fi cnt1=`ps aux | grep hostapd | grep -v grep | wc -l` if [ "${cnt1}" != "0" ];then killall hostapd > /dev/null fi /etc/init.d/S80dnsmasq stop echo 1 > /proc/sys/net/ipv4/ip_forward #iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE sleep 1 ifconfig wlp1s0 192.168.2.1 hostapd /etc/hostapd-2.4g.conf & #hostapd /etc/hostapd-5g.conf & /etc/init.d/S80dnsmasq start
That's all for the fltest _ hostapd. sh script. In the fltest _ hostapd. sh script, the/etc/hostapd-2.4g.conf configuration file is also used, and the following is the configuration content of the file:
interface=wlp1s0 driver=nl80211 channel=9 hw_mode=g auth_algs=1 ieee80211n=1 wpa=1 ssid=OK3576_WIFI_2.4G_AP //AP mode wifi name wpa_passphrase=12345678 //AP mode WiFi password wpa_key_mgmt=WPA-PSK wpa_pairwise=TKIP rsn_pairwise=CCMP
Next, configure the dnsmasq. conf service.
root@rk3576-buildroot:/root# vi /etc/dnsmasq.conf interface=wlp1s0 bind-interfaces except-interface=lo dhcp-range=192.168.2.100,192.168.2.254,12h dhcp-option=3,192.168.2.1 dhcp-option=6,192.168.2.1
Some users might ask why udhcpd is used in other systems, while DNSmasq is chosen here. Here's a brief comparison of the two services:
(1)udhcpd A DHCP server from the BusyBox toolkit. Assigns dynamic IP addresses, subnet masks, gateways, etc., to local network devices. Does not include DNS forwarding or other network services.
(2)DNSmasq A lightweight DNS forwarder and DHCP server.
① Forwards DNS queries to upstream servers and caches results to improve response times.
② As a DHCP server, its functionality is similar to udhcpd (not repeated here).
Primarily used in small networks (e.g., home networks, small offices, routers) due to its ease of configuration and management. In contrast, udhcpd is better suited for embedded systems or resource-constrained environments.
After the introduction of extended knowledge, the AP mode is opened:
root@rk3576-buildroot:/root# fltest_hostapd.sh [ 6470.256308] wlp1s0: deauthenticating from ee:b9:70:81:7d:88 by local choice (Reason: 3=DEAUTH_LEAVING) killall: hostapd: no process killed Stopping dnsmasq: FAIL Starting dnsmasq: OK [ 6471.641533] IPv6: ADDRCONF(NETDEV_CHANGE): wlp1s0: link becomes ready wlp1s0: interface state UNINITIALIZED->ENABLED wlp1s0: AP-ENABLED root@rk3576-buildroot:/root# ifconfig wlp1s0 wlp1s0 Link encap:Ethernet HWaddr 4C:49:6C:F0:99:7A inet addr:192.168.2.1 Bcast:192.168.2.255 Mask:255.255.255.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:50382 errors:0 dropped:2982 overruns:0 frame:0 TX packets:261 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:4291281 (4.0 MiB) TX bytes:27170 (26.5 KiB)
The following is the hot spot to use mobile phone to connect to the embedded OK3576-C development board.
root@rk3576-buildroot:/root# ping 192.168.2.225 PING 192.168.2.225 (192.168.2.225) 56(84) bytes of data. 64 bytes from 192.168.2.225: icmp_seq=1 ttl=64 time=142 ms 64 bytes from 192.168.2.225: icmp_seq=2 ttl=64 time=60.1 ms 64 bytes from 192.168.2.225: icmp_seq=3 ttl=64 time=88.2 ms 64 bytes from 192.168.2.225: icmp_seq=4 ttl=64 time=110 ms 64 bytes from 192.168.2.225: icmp_seq=5 ttl=64 time=69.9 ms ^C --- 192.168.2.225 ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 4004ms
At this point, the new AX210NGW Wi-Fi 6E module has been successfully adapted.
The adaptation approach for PCIe Wi-Fi modules is consistent. If other Wi-Fi modules are involved, this method can also serve as a reference for implementation.