多年前入手了一个 Cubieboard2,玩了一段时间后就刷上了官方的 debian-sever 镜像放家里当 NAS 用。最近整理家里的物件,想把 Cubieboard2 改成无线入网,就按文档购入了水星 MW150US 无线网卡。满心欢喜收的到货,却发现根本不能用,原来这个型号的网卡已经换代,芯片已不是 8192cu,而是更便宜的 MT7601U 了。

8192cu 是螃蟹厂的,MT7601U 是联发科的,国内一众如小度wifi、360随身wifi、小米随身wifi等等都是用的后者,TP-LINK 又一次用实力展示了『缩水之王』的称号绝非浪得虚名。

我能怎么办,我也很无奈,当然是自己编一个驱动咯。

硬件及系统环境

硬件:Cubieboard2 双卡板

系统:官网提供的 Debian-server

网卡:水星 MW150US (MT7601U)

root@cubieboard2:~# uname -a
Linux cubieboard2 3.4.79 #1 SMP PREEMPT Fri Nov 14 11:39:56 CST 2014 armv7l GNU/Linux

root@cubieboard2:~# lsusb -v
Bus 004 Device 002: ID 148f:7601 Ralink Technology, Corp. MT7601U Wireless Adapter
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.01
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0        64
  idVendor           0x148f Ralink Technology, Corp.
  idProduct          0x7601 MT7601U Wireless Adapter
  bcdDevice            0.00
  iManufacturer           1 MediaTek
  iProduct                2 802.11 n WLAN
  iSerial                 3 1.0
  bNumConfigurations      1
  . . .

编译

交叉编译环境准备

这里有两个选择:本机编译 vs 交叉编译,考虑到 Cubieboard2 的性能,基本上等于找虐,所以我选择用 docker 交叉编译,既不用担心破坏工作机的环境,又可以避免准备编译环境时遇到各种乱七八糟的问题。

// beginor/ubuntu-china 是随便找的一个使用阿里云镜像的 ubuntu 镜像
$ docker run -it --rm -v /tmp/cubie:/root beginor/ubuntu-china /bin/bash

// 进入容器后
# apt-get update
# apt-get install git vim
# apt install gcc-4.7 g++-4.7 gcc-4.7-multilib gcc g++-4.7-multilib \
  gcc-4.7-arm-linux-gnueabihf g++-4.7-arm-linux-gnueabihf make

注意需要使用 gcc-4.7,如果在 gcc 版本上遇到问题请参考荔枝派的一篇文章:

那些年我们踩的坑/编译坑_Ubuntu 2016.04编译过程踩坑记录

linux kernel 环境准备

下载 cubieboard 的内核源码,注意选择对应的版本分支,比如我的是 3.4.79

$ cd ~
$ git clone -b cubie/sunxi-3.4.79 https://github.com/cubieboard/linux-sunxi.git --depth=1
$ cd linux-sunxi

准备 .config 文件

到 Cubieboard2 上执行 zcat /proc/config.gz 将内容复制并保存为 .config 文件(内核文件根目录)

也可以直接生成一个

$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- cubieboard2_defconfig

生成 generated 的头文件和 version.h

$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- prepare

产生 scripts 工具

$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- scripts

make prepare 和 make scripts 两步也可以用下面代替

$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules_prepare

MT7601U 驱动编译

  • 下载源码

    官网地址:[](https://www.mediatek.com/products/broadbandWifi/mt7601u)

    最新的驱动应该依旧是 DPO_MT7601U_LinuxSTA_3.0.0.4_20130913 这个版本,这里就直接用一位网友的仓库,他还添加了几种国内常见设备的编码(360wifi、小米wifi之类的)

    $ cd ~
    $ git clone https://github.com/jfojfo/MT7601U.git --depth=1
    $ cd MT7601U
    
  • 指定平台

    修改 Makefile,在 export LINUX_SRC CROSS_COMPILE 之前添加

    # add following 2 lines
    LINUX_SRC=../linux-sunxi
    CROSS_COMPILE=arm-linux-gnueabihf-
        
    export OSABL RT28xx_DIR RT28xx_MODE LINUX_SRC CROSS_COMPILE CROSS_COMPILE_INCLUDE PLATFORM RELEASE CHIPSET MODULE RTMP_SRC_DIR LINUX_SRC_MODULE TARGET HAS_WOW_SUPPORT
        
    # The targets that may be used.
    PHONY += all build_tools test UCOS THREADX LINUX release prerelease clean uninstall install libwapi osabl
    
  • 关闭 DEBUG 日志输出

    源码中 DEBUG 的等级是 RT_DEBUG_TRACE,这会导致你的终端被大量 DEBUG 日志刷屏,所以一定记得要改

    /* os/linux/rt_linux.c:54 */
    ULONG RTDebugLevel = RT_DEBUG_TRACE;
    /* 改为 */
    ULONG RTDebugLevel = RT_DEBUG_OFF;
    
  • 修改 DEV_NAME (可选)

    默认的设备名称是「ra」,也就是安装完后会在 ifconfig 里面看到一个叫 「ra0」的网卡设备,如果想修改为更为常见的「wlan0」,修改 include/rtmp_def.h 的 1604、1605 行

    #define INF_MAIN_DEV_NAME       "wlan"
    #define INF_MBSSID_DEV_NAME     "wlan"
    
  • 编译

    $ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
    

    编译好的驱动文件在 os/linux/mt7601Usta.ko

安装

  1. 创建 /etc/Wireless/RT2870STA/ 目录,将驱动源码根目录下的 RT2870STA.dat 拷贝到这个目录下

  2. 将编译好的 mt7601Usta.ko 文件拷贝到 Cubieboard2 的 wireless 驱动目录下,我这个版本的 Debian 在 /lib/modules/3.4.79/kernel/drivers/net/wireless/,不同的系统可能略微有点不同

  3. 运行

    root@cubieboard2:~# depmod -a
    root@cubieboard2:~# modprobe mt7601Usta
    

插上网卡,执行 lsmod,能看到 mt7601Usta 就加载成功了

root@cubieboard2:~# lsmod
Module                  Size  Used by
mt7601Usta            780077  0
g_mass_storage         43190  0
cpufreq_stats           3675  0
bluetooth             265092  0
mali                  113805  0
ump                    51020  1 mali
lcd                     3630  0
pwm_sunxi               8987  0
gpio_sunxi              8910  0

ifconfig -a 应该能看到 wlan0 (或者 ra0),驱动成功。

修改 DMA 大小

前面编译出来驱动,insmod 时会发现出错,报 DMA 内存不足,Cubieboard2 中默认使用 256K,需要修改成 1M 以上

注:如果你发现 lsmod 中已经加载了 mt7601Usta,但是 ifconfig -a 没有对应的网卡,可能是你错过了 insmod 的报错,可以使用 dmesg | tail 查看

--> RTMPAllocTxRxRingMemory
ERROR: 256 KiB atomic DMA coherent pool is too small!
Please increase it with coherent_pool= kernel parameter!

此时需要修改系统的 bootargs,Cubieboard2 采用的是 U-boot,大多可以通过 uEnv.txt 来修改 bootargs。为什么是大多?因为能否修改取决于 boot.cmd 在 setenv bootargs 时是否预留了 ${extraargs} 参数,如果没有那可能就只能重新烧写SD卡了。关于这一点,请参见 uEnv.txt的使用 一文。

df -h 检查一下 /dev/mmcblk0p1 是否有挂载,如果没有则 mount /dev/mmcblk0p1 /boot 挂载到 /boot

查看 /boot 下是否有 uEnv.txt 文件,如果有并且里面已经有 extraargs=...,就在最后追加 coherent_pool=2M

如果没有,先查看当前启动参数

root@cubieboard2:~# cat /proc/cmdline
console=ttyS0,115200 root=/dev/sda1 loglevel=8 panic=10 console=tty0 hdmi.audio=EDID:0 disp.screen0_output_mode=EDID:1280x720p50 rootwait panic=10 rootfstype=ext4 rootflags=discard

添加 /boot/uEnv.txt 并写入

root=/dev/sda1
extraargs=console=tty0 hdmi.audio=EDID:0 disp.screen0_output_mode=EDID:1280x720p50 rootwait panic=10 rootfstype=ext4 rootflags=discard coherent_pool=2M

重启,再用 cat /proc/cmdline 检查是否成功,如若不行请去查找系统的相关文档或重新烧写SD卡

配置 WIFI

这步就是小问题了,来一个我常用的方法

root@cubieboard2:~# wpa_passphrase ESSID PASSWORD > /etc/wpa_supplicant.conf

在 /etc/network/interfaces 中添加如下内容:

auto wlan0
iface wlan0 inet dhcp
wpa-conf /etc/wpa_supplicant.conf
root@cubieboard2:~# ifup wlan0

总结

编译本身并不麻烦,但是由于 Cubieboard2 比较小众,使用官方的 Debian 的就更少了,各种疑难杂症,掉坑填坑,居然花了一天的时间来折腾,到底是值得还是不值得呢?感觉自己又学到了很多东西,只怕是回头便又忘得一干二净了,零散的知识没有连成框架,其实比「知识付费」买来的「经历」也强不到哪儿去,这大概就是「时间付费」吧。


参考文章:

  1. Cubieboard2使用小米wifi
  2. cubieboard 折腾手记