This guide describes how to build and install the AIC8800 wireless LAN driver for the Rux robot running Debian (ARM64). Rux is a robot developed by LeTianPai. The driver must be cross-compiled for ARM64 and loaded manually for testing.
Note: These instructions are experimental. Proceed with caution and at your own risk.
Before starting, make sure your kernel matches the tested environment.
Please follow the first section of the official guide to install ADB tools.
Reference: Rux official installation guide.
> adb shell
(On Android) $ uname -a
Linux localhost 4.19.232-ab351 #219 SMP PREEMPT Tue Feb 27 15:49:29 CST 2024 aarch64
Make sure it matches your Rux environment.
Follow the official documentation to flash the full ROOT ROM.
Reference: Rux official installation guide
Then, switch to the debian environment by running adb root
and adb shell bootdebian.sh
.
(On Debian) # uname -a
Linux linaro-alip 4.19.232 #3 SMP Sat Apr 22 18:43:58 CST 2023 aarch64 GNU/Linux
Check again that the environment matches in the Debian system as well.
Cross Compiler: gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu.tar.xz (Download page)
Linux Kernel Source (4.19 branch):
rockchip-linux/kernel (checkout the develop-4.19
branch)
Wi-Fi Driver Source (AIC8800):
radxa-pkg/aic8800 (checkout the 3.0+git20240327.3561b08f-7
)
Before building the AIC8800 driver, you need to prepare the Linux kernel source tree so that it matches the configuration of your Rux device.
a) Extract the current kernel configuration from the device
Transfer /proc/config.gz from Rux with adb pull
, then run:
$ zcat config.gz > .config
Move this .config into the kernel source directory.
b) Prepare the kernel for external module builds
Inside the kernel source directory, run the following commands.
(Replace /path/to/*
with the actual directory where you downloaded.)
$ export ARCH=arm64
$ export CROSS_COMPILE=/path/to/aarch64-none-linux-gnu-
$ cd /path/to/kernel
$ make olddefconfig
$ make modules_prepare
After this step, the kernel source tree will contain the necessary headers and generated files (include/generated/*), and you can proceed with building the driver.
In the driver source, patch the set_ios
handling:
If host->ops->set_ios
is NULL
, skip the call and print a WARNING instead of crashing.
--- ./src/SDIO/driver_fw/driver/aic8800/aic8800_bsp/aicsdio.c.org
+++ ./src/SDIO/driver_fw/driver/aic8800/aic8800_bsp/aicsdio.c
@@ -1705,12 +1705,24 @@
return ret;
}
udelay(100);
-#if 1//SDIO CLOCK SETTING
+#if 0//SDIO CLOCK SETTING
if (feature.sdio_clock > 0) {
host->ios.clock = feature.sdio_clock;
host->ops->set_ios(host, &host->ios);
sdio_dbg("Set SDIO Clock %d MHz\n", host->ios.clock/1000000);
}
+#else
+ if (feature.sdio_clock > 0) {
+ if (host && host->ops && host->ops->set_ios) {
+ host->ios.clock = feature.sdio_clock;
+ host->ops->set_ios(host, &host->ios);
+ sdio_dbg("Set SDIO Clock %d MHz\n", host->ios.clock/1000000);
+ AICWFDBG(LOGINFO, "Set SDIO Clock %d MHz\n",
+ host->ios.clock/1000000);
+ } else {
+ AICWFDBG(LOGINFO, "Skipped clock change: set_ios unavailable!\n");
+ }
+ }
#endif
sdio_release_host(sdiodev->func);
--- ./src/SDIO/driver_fw/driver/aic8800/aic8800_fdrv/aicwf_sdio.c.org
+++ ./src/SDIO/driver_fw/driver/aic8800/aic8800_fdrv/aicwf_sdio.c
@@ -2266,12 +2266,24 @@
return ret;
}
-#if 1//SDIO CLOCK SETTING
+#if 0//SDIO CLOCK SETTING
if (feature.sdio_clock > 0) {
host->ios.clock = feature.sdio_clock;
host->ops->set_ios(host, &host->ios);
AICWFDBG(LOGINFO, "Set SDIO Clock %d MHz\n", host->ios.clock/1000000);
}
+#else
+ if (feature.sdio_clock > 0) {
+ if (host && host->ops && host->ops->set_ios) {
+ host->ios.clock = feature.sdio_clock;
+ host->ops->set_ios(host, &host->ios);
+ sdio_dbg("Set SDIO Clock %d MHz\n", host->ios.clock/1000000);
+ AICWFDBG(LOGINFO, "Set SDIO Clock %d MHz\n",
+ host->ios.clock/1000000);
+ } else {
+ AICWFDBG(LOGINFO, "Skipped clock change: set_ios unavailable!\n");
+ }
+ }
#endif
sdio_release_host(sdiodev->func);
Export the cross-compiler and build the driver:
$ export ARCH=arm64
$ export CROSS_COMPILE=/path/to/aarch64-none-linux-gnu-
$ cd /path/to/aic8800/src/SDIO/driver_fw/driver/aic8800
$ make -C /path/to/kernel M=$PWD CONFIG_PLATFORM_UBUNTU=y CONFIG_USE_FW_REQUEST=y EXTRA_CFLAGS="-DCONFIG_PLATFORM_ROCKCHIP" modules -j"$(nproc)"
Copy the built .ko
files (e.g., aic8800_bsp.ko
, aic8800_fdrv.ko
) to the Debian filesystem on Rux using adb push
, typically under:
/lib/modules/$(uname -r)/kernel/drivers/net/wireless/aic8800/
The Wi-Fi chip is connected via dwmmc@fe2c0000
. Reset it by unbinding and rebinding:
# echo fe2c0000.dwmmc > /sys/bus/platform/drivers/dwmmc_rockchip/unbind
# sleep 0.6
# echo fe2c0000.dwmmc > /sys/bus/platform/drivers/dwmmc_rockchip/bind
Tip: You can identify the correct SDIO host device name (e.g., fe2c0000.dwmmc
) by checking the boot log:
# dmesg | grep mmc-pwrseq
Insert the driver:
# depmod -a
# modprobe -v aic8800_fdrv
If successful, the wlan0 device should appear in:
# ip a
Use NetworkManager (nmcli) for connection:
# nmcli radio wifi on
# nmcli -w 60 dev wifi list ifname wlan0 --rescan yes
# nmcli dev wifi connect "SSID" ifname wlan0
(After the first time: the saved connection can be brought up directly)
# nmcli con up id "SSID" ifname wlan0