一、开启usb功能
linux开启某项功能的三步,设备树,驱动,应用。
1、设备树添加usb设备节点
1、linux5.7.1已经对全志系列芯片进行了支持,可惜的是f1c200s并不在其中,不过关于usb的驱动,可以借鉴a10型号,并做出一些修改。
2、添加驱动第一步,修改设备树。修改设备树之前,通过源码中Documentation下的帮助文档,找到关于usb设备树的参考写法。具体路径在Documentation\devicetree\bindings\usb\allwinner,sun4i-a10-musb.yaml
3、将上述复制到我们的设备树文件suniv-f1c100s.dtsi中,逐条进行优化。
//优化后
usb_otg: usb@1c13000 {
compatible = "allwinner,sun4i-a10-musb";
reg = <0x01c13000 0x0400>;
clocks = <&ccu CLK_BUS_OTG>;
resets = <&ccu RST_BUS_OTG>;
interrupts = <26>;
interrupt-names = "mc";
phys = <&usbphy 0>;
phy-names = "usb";
extcon = <&usbphy 0>;
dr_mode = "otg";
allwinner,sram = <&otg_sram 1>;
status = "disabled";
};
a、usb_otg: usb@1c13000:设备节点,以及对应的寄存器,查阅芯片手册寄存器地址同样是1c13000。冒号前是给节点起的名字。
b、compatible = “allwinner,sun4i-a10-musb”:指定设备所使用的驱动,这里也不做修改,借用a10的驱动程序。
c、reg = <0x01c13000 0x0400>:参考a中图片,这里也不需要修改。
d、clocks = <&ccu CLK_BUS_OTG>:首先看clocks,可以知道这是配置时钟的。但是<&ccu CLK_BUS_OTG>又是什么意思呢,如果你仔细查看了设备树文件,就会发现ccu也是一个设备,也就是时钟管理单元。所以回头来看,时钟也被定义为设备了,其他设备使用时钟时,调用时钟设备。
resets = <&ccu RST_BUS_OTG>:指定usb设备的复位单元。
这里博主也没有找到更换时钟的原因,但是联系到下面一些修改都是围绕时钟,猜测f1c200s可能对ahb的支持有些问题。
e、interrupts = <26>:设置usb的中断号,查看手册获得。
interrupt-names = “mc”:设置中断名称,驱动程序中可以通过名字获取中断相关的结构体。
f、phys = <&usbphy 0>:usb功能分为控制层和物理层两个部分,我们配置的usb_otg是控制层,控制层依托于物理层,所以还需要配置phys。usbphy是物理层设备节点,会在下文解析。
phy-names = “usb”:设置关联的名称。
g、extcon = <&usbphy 0>:extcon是外部连接器。usb接口类型有TypeA/B、TypeC等,每种接口类型的硬件检测方式也不一样,有了extcon就可以把不同类型的接口整合为一个统一的标准,用以供驱动程序使用。
h、dr_mode = “otg”:一般来说,USB 设备有两种,一种是 Host,比如电脑,可以去读取其他 USB 设备的数据,另外一种是 Device,比如键盘鼠标U盘智能手机。而OTG实现了设备在host 和 slave(peripheral)间转换。
i、allwinner,sram = <&otg_sram 1>; 这一项是对内存的设置,之所以原来没有,是因为原来的dr_mode模式为peripheral,不需要配置内存。这一项被调用的位置也不在usb驱动文件内,博主找了很久才发现,是在文件drivers/soc/sunxi/sunxi_sram.c的第175行进行的调用。
内存在设备树文件内已经被默认配置了,并且也是otg模式(其实就是把内存分为系统部分和otg部分两大块),所以博主理解这里为,指定内存第二区域被otg使用。
这里不要被迷惑了,其实allwinner,sram是一个整体,可以理解为一个带逗号的字符串。
2、设备树添加usb物理层节点
1、承接上一小节的f项,usb需要物理层的支持,相关的帮助文档在路径Documentation\devicetree\bindings\phy\allwinner,sun4i-a10-usb-phy.yaml下
2、从下图可以看出,f1c200s仅仅只有一个usb接口,所以同样的,需要对设备节点进行修改。
usbphy: phy@1c13400 {
#phy-cells = <1>;
compatible = "allwinner,sun4i-a10-usb-phy";
reg = <0x01c13400 0x10>;
reg-names = "phy_ctrl";
clocks = <&ccu CLK_USB_PHY0>;
clock-names = "usb0_phy";
resets = <&ccu RST_USB_PHY0>;
reset-names = "usb0_reset";
usb0_id_det-gpio = <&pio 4 2 GPIO_ACTIVE_HIGH>;
status = "disabled";
};
a、usbphy: phy@1c13400 { 寄存器地址,被包含在usb-otg设备地址内,但是从手册中并没有查找到。
b、#phy-cells = <1>; 从帮助文档Documentation\devicetree\bindings\phy\allwinner,sun4i-a10-usb-phy.yaml的14行位置,可以看出,这个选项只能赋值1。但是它究竟是什么功能呢?
其实多查看几个同路径下其他文件的说明,就会发现它指的是PHY的接口类型,可能是usb,也可能是stat、SGMII,具体要看对应的芯片。
c、reg = <0x01c13400 0x10>; 因为f1c200s只有一个物理接口,所以就把其他的寄存器删除掉了。
d、usb0_id_det-gpio = <&pio 4 2 GPIO_ACTIVE_HIGH>;
前面说过,USB是有Host和Device之分的,那怎么区分这两种设备的,没错,就是通过id脚。id脚为低电平时,表示设备是Host,id脚为高电平时,设备为Device。
那为什么自己兜里的U盘只有四个金属片呢?众所周知<_<,U盘有Vcc、D+、D-、Gnd四条线,id线在哪里呢?ID线已经被内部拉低了(U盘上电瞬间检测到低电平,认为自己接到了主设备上,就能正常通信了),所以就没有引出来。
所以呢,这里设置id脚就不难理解了。OTG通过ID脚判断对方是什么设备,进而把自己转换为对应的设备,进行通信。可惜的是,这个脚在原理图上看,是悬空的。
3、配置设备树的最后一步,就是把相应的设备状态都打开。打开文件suniv-f1c100s-licheepi-nano.dts,添加如下部分。
&otg_sram {
status = "okay";
};
&usb_otg {
status = "okay";
};
&usbphy {
status = "okay";
};
3、修改驱动文件
1、经过上面的一番修改,设备树已经修改完成了。接下来就是打开USB驱动,打开驱动依然是在配置菜单内进行。首先执行make menuconfig打开菜单。然后在Device Drivers内打开USB support,以及USB support内的Highspeed Dual Role Controller,当然应该默认已经打开了。
2、然后编译,拷贝,上电测试,你就会惊奇的发现,有报错>_<。报错提示我们,usb没有重置。仔细回想一下,我们在添加usb设备节点时做了什么,对!我们修改了时钟。
3、所以接下来,就要针对时钟进行修改,打开文件drivers/phy/allwinner/phy-sun4i-usb.c,找到sun4i_a10_cfg,然后把dedicated_clocks修改为true,也就是指定驱动使用专用时钟。
4、最后在文件drivers/usb/musb/sunxi.c中,大概在727行,给初始化的条件加上对sun4i-a10-musb的判断。
5、做完上述步骤,设备就可以愉快的使用u盘了。
二、添加网卡驱动
1、但是还不能止步于此,因为我们的目标是使用无线网。凑巧博主手中还有陈年古董,NW362无线网卡一张,就用它了。当然如果是自行画板,可以使用8188模块,直接贴板使用。
2、网卡作为设备,自然也逃不过配置设备树的命运,但是无线网卡依托与usb接口,所以直接进行驱动配置就可以了。首先在菜单Networking support->wireless里,打开cfg80211 wireless extensions compatibility。
cfg80211用于在内核空间中对无线设备进行配置管理。cfg80211 wireless extensions compatibility是什么意思呢?一些使用基于cfg80211的驱动扩展可能需要使用一个老的用户空间,打开这个选项,用于支持这些功能,比如iwconfig命令。
3、接下来添加网卡驱动。把网卡先插入到windows电脑,从设备管理器可以看出,NW362这款网卡是瑞昱的芯片,型号为TRTL8192CU
所以就进入到菜单Device Drivers->Network device support->wireless LAN位置,打开realtek devices驱动就可以了,TRTL8192CU已经被包含进rtlwifi family里面了。
4、编译、复制、重启、插入网卡、然后就报错<_<。报错提示我们,加载文件rtlwifi/rtl8192cufw_TMSC.bin…失败。那是因为这些可执行文件,是以lib的方式放在文件系统内调用的,所以还需要把对应网卡的二进制文件放入指定的文件夹下。
5、二进制文件可以从官网下载
git clone https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git
下载完成之后,文件夹linux-firmware/rtlwifi内就包含了我们需要的文件。将其中所有文件复制到开发板(Tf卡roots分区)的/lib/firmware/rtlwifi下,如果没有的话就创建目录再复制,并且需要为目录设置权限。再次插入网卡,就能正常加载文件了。
三、测试网络
1、首先执行命令ifconfig -a。由下图可知,网卡已经被识别了。并且可知,网卡的设备名为wlan0。
2、接下来配置无线网卡,使其能连接到路由器上。不过在进行配置之前,先要安装工具wpa_supplicant,wpa_supplicant是WiFi驱动和上层用户的中转站,以及对协议和加密认证的支持。安装步骤可以参考第三章。
在开发板上,执行命令vi /etc/wpa_supplicant.conf,创建一个配置文件,并在文件内输入如下内容。
ctrl_interface=/var/run/wpa_supplicant
ap_scan=1
network={
ssid="账号"
key_mgmt=WPA-PSK
proto=WPA2
pairwise=CCMP
psk="密码"
}
ctrl_interface:wpa_cli前端程序与wpa_supplicant后台交互时使用的socket控制接口,可以简单理解为工作目录。
ap_scan:是指定设备的扫描方式,1使用wpa_supplicant来扫描和选择AP,0使用驱动来扫描及选择AP,2和0相同区别在于增加安全策略。
network:需要连接的wifi信息。
3、执行mkdir /var/run/wpa_supplicant -p,创建一个文件夹。-p参数表示,若路径不存在,则会创建路径。
启动连接wpa_supplicant -D wext -c /etc/wpa_supplicant.conf -i wlan0 &
wpa_supplicant -D wext -c /etc/wpa_supplicant.conf -i wlan0 &
-D:驱动名称
nl80211 = Linux nl80211/cfg80211
wext = Linux wireless extensions (generic)
wired = Wired Ethernet driver
-c:配置文件
-i:网口名称
&:后台运行
更多命令执行wpa_supplicant --help
udhcpc -i wlan0 //自动获取ip
最后ping一下百度,大工告成
4、另外
ifconfig wlan0 192.168.1.222 netmask 255.255.255.0
设置ip和子网掩码
route add default gw 192.168.1.1
设置网关
三、安装wpa_supplicant
1、安装wpa_supplicant之前,需要先行安装其所需要的库。首先安装openssl
wget https://www.openssl.org/source/openssl-1.1.1d.tar.gz
#先到官网下载对应的源码
tar -vxf openssl-1.1.1d.tar.gz
#解压缩
cd openssl-1.1.1d
#进入对应的目录
./config no-asm shared --prefix=/usr/local/software/openssl-1.1.1d/install CROSS_COMPILE=arm-buildroot-linux-uclibcgnueabi-
#编译前的配置,指定安装路径和编译器。注意路径最好修改为自己源码的路径,方便安装后查找lib文件
vim Makefile
#打开makefile文件
去掉126和127的-m64
#删除掉异常报错的选项
make
#执行编译
make install
#执行安装
2、安装libnl,和上面步骤差不多
wget https://github.com/thom311/libnl/releases/download/libnl3_7_0/libnl-3.7.0.tar.gz
#首先下载源码
tar -vxf libnl-3.7.0.tar.gz
#解压缩
cd libnl-3.7.0
#进入源码路径
./configure --host=arm-buildroot-linux-uclibcgnueabi --prefix=$(pwd)/install
#指定编译器和安装路径
make -j4
#执行编译, -j4是指使用四颗处理器核心一起编译
make install
#执行安装
3、安装wpa_supplicant
wget http://w1.fi/releases/wpa_supplicant-2.7.tar.gz
#下载源码
tar -vxf wpa_supplicant-2.7.tar.gz
#解压缩
cd wpa_supplicant-2.7/wpa_supplicant
#进入源码路径
cp defconfig .config
#复制默认配置
执行vim .config,打开配置文件,修改编译器,并且添加依赖库openssl和libnl的路径。
CC = arm-buildroot-linux-uclibcgnueabi-gcc
CFLAGS += -I /usr/local/software/openssl-1.1.1d/install/include
LIBS += -L /usr/local/software/openssl-1.1.1d/install/lib
CFLAGS += -I /usr/local/software/libnl-3.7.0/install/include
LIBS += -L /usr/local/software/libnl-3.7.0/install/lib
执行export PKG_CONFIG_PATH=/usr/local/software/libnl-3.7.0/install/lib/pkgconfig/,指定PKG_CONFIG_PATH的路径。
执行make -j4进行编译。
4、以上步骤全部做完以后。
将文件夹openssl-1.1.1d/install/lib下的所有文件复制到开发板(Tf卡roots分区)的/usr/lib目录
将文件夹libnl-3.7.0/install/lib下的所有文件复制到开发板(Tf卡roots分区)的/usr/lib目录
将文件夹wpa_supplicant-2.7/wpa_supplicant下的wpa_cli和wpa_supplicant复制到开发板(Tf卡roots分区)的/usr/bin目录。
5、这样,wpa_supplicant就已经安装到开发板上啦。