该文章仅供参考,编写人不对任何实验设备、人员及测量结果负责!!!
0 引言
文章主要介绍King3399(ubuntu)wifi设备树,涉及king-rk3399.dts、rp-wifi-sdio.dtsi内容修改与介绍
在使用wifi前本人遇到了一个比较奇怪的问题,即自行编译的镜像文件烧录后无法使用wifi功能,使用指令ip a
查看时没有wlan这部分,配置界面也没有相关选项,具体情况如下图所示,摸索一周后不清楚修改了哪里wifi又可正常启用(非设备树问题,因为对比前后逆向生成设备树文件各项配置相同,故排除设备树)
一开始我认为是设备树的问题,因为rp-wifi-sdio.dtsi
中的属性为wifi_chip_type = "ap6210";
,而板子的wifi型号为ap6354s,将该属性修改后重新编译boot.img并烧录,wifi依然无法正常启用,于是便想从官方的镜像中获取设备树,对比从SDK中自行编译的设备树之间的区别
这篇文章具有一定的局限性:需要一个完整且功能正常的镜像做为参考
1 wifi模块硬件分析
king3399可以通过有线网络、无线wifi与4G模块三种方式联网,在进行开发时,大多数情况下都是利用有线的方式,这种方式更为稳定且在软件层面配置也较为简单,硬件上仅仅是多一根网线,但这也有一定局限性,例如当下无线网的应用更为广泛,利用手机的热点就可以组成局域网,随时随地都可以进行开发,免去杂乱的布线困扰,前面的文章本人使用的是有线的方式,最近将wifi的部分研究后,对这部分进行总结
cdrom_king3399_new\03-硬件文档\底板硬件资料\KING3399-20180712原理图.pdf
在上述路径中可以找到板子的原理图,其中wifi部分硬件原理图如下图所示(该模块为wifi+BT,本文只涉及wifi部分),模块外围电路并不复杂,采用SDIO接口与主控通信
wifi模块使用型号为ap6354,这个模块在正基(AMPAK)官网已下架,但网上有大量相关资料,datasheet(ap6354/ap6210)可在文末链接中下载
2 设备树分析
建议在查看设备树文件前先对其进行备份,避免误修改!!!
wifi这部分涉及多个设备树文件与子系统,在节点中有大量有用/无用的属性,如果刚接触这块内容学习起来是比较困难的,这里分享一个方法:逆向分析设备树,学习过设备树知识的应该都知道设备树这部分内容其实并不难(仅看懂与会修改),子节点的配置类似于stm32硬件的初始化,个人觉得难点在于节点内部属性的引用以及属性的具体意义
首先是引用,设备树中为了便于修改与配置,会使用大量的“&”对变量名进行引用,相对于直接写一堆数字/地址确实有助于分析代码,但这也会导致同一个变量名可能会出现在多个文件中,当使用“&”对一个子节点引用时就要注意了,这可能是对其属性的初始化,也可能是对其属性修改,还有可能是添加某个属性,当涉及多个文件与属性时,很容易迷糊
其次是属性,每个子节点都是由大量的属性组成,部分属性是固有的,这些在修改前必须了解,还有部分是第三方自定义的,这部分非常重要,通常具有极强针对性,但这部分可查找资料有限,往往需要根据实际情况推测
cdrom_king3399_new\04-镜像文件\ubuntu2004\update-king3399-linux-ubuntu20-hdmi-xxx-xxx.img
这里详细记录一下前文提到的逆向分析设备树的方法,首先将官方提供的镜像烧录至板子中,(可参考上述路径选择性下载,建议选择的镜像版本与SDK生成的版本一致,不同版本的设备树会有些许差异,不便于分析具体的差异),板子成功启动后执行如下指令安装设备树编译器
sudo apt install device-tree-compiler
查看当前板子所用设备树文件内容
dtc -I fs -O dts /sys/firmware/devicetree/base # -I是大写的 i !!!
为便于查看可将上述指令结果输出到指定文件,该过程可能会产生大量警告日志,可不理会
touch /home/xxx/my_king3399_dts.dts # 创建一个空设备树文件
将设备树输出到该文件
dtc -I fs -O dts /sys/firmware/devicetree/base > /home/xxx/my_king3399_dts.dts
上述操作皆在板子上执行,随后打开主机进入目录~/ws/sdk/kernel/arch/arm64/boot/dts/rockchip/rk3399
,打开king-rk3399.dts
可以看到,
#include "rp-rk3399-board.dtsi"
......
#include "rp-audio-rt5651.dtsi"
#include "rp-pmu-rk808.dtsi"#include "rp-gpio-key.dtsi"
#include "rp-adc-key.dtsi"#include "rp-mipi-ov13850-camera.dtsi"#include "rp-wifi-sdio.dtsi" // <----------目标文件
#include "rp-bt-uart0.dtsi" #include "rp-sdcard-mmc1.dtsi"
#include "rp-gmac.dtsi"
......
从头文件不难看出rp-wifi-sdio.dtsi
是我们需要关注的文件,在同级目录下打开该文件,内容如下,内部共有三个子节点,其中wireless_wlan
为新添加的节点,&sdio0
与&pinctrl
为引用节点,为便于理解,对各属性添加必要注释
/ {wireless_wlan: wireless-wlan {# 兼容性匹配检查用compatible = "wlan-platdata";# grf: general register filerockchip,grf = <&grf>;# wifi模块型号,这里填写ap6354也可正常使用wifi_chip_type = "ap6210";# sdio_vref = <1800>;pinctrl-names = "default";pinctrl-0 = <&wifi_host_wake_irq>, <&wifi_enable_h>;# 中断控制引脚WIFI,host_wake_irq = <&gpio0 RK_PA3 GPIO_ACTIVE_HIGH>; # 电源控制引脚WIFI,poweren_gpio = <&gpio0 RK_PB2 GPIO_ACTIVE_HIGH>;# 节点状态可用status = "okay";};
};# sdio0 = "/mmc@fe310000";
&sdio0 {# SDIO最大运行频率max-frequency = <150000000>;# 在初始化时是否限制发送sd指令no-sd;# 在初始化时是否限制发送mmc指令no-mmc;# 线宽,不配置则默认为1,可选择参数只有1、4和8bus-width = <4>;# 是否禁用写保护disable-wp;# 是否为高速设备cap-sd-highspeed;# 是否支持中断cap-sdio-irq;# 是否支持睡眠不断电 keep-power-in-suspend;# 插槽不可移动non-removable;#num-slots = <1>;pinctrl-names = "default";pinctrl-0 = <&sdio0_bus4 &sdio0_cmd &sdio0_clk>;# 设备是否支持 SDIO3.0 模式(频率 < 208M)sd-uhs-sdr104;status = "okay";
};&pinctrl {wireless-wlan {wifi_host_wake_irq: wifi-host-wake-irq {rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_down>;};wifi_enable_h: wifi-enable-h {rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>;};};
};
与此同时打开前面逆向生成的设备树my_king3399_dts.dts,摘取部分与本文相关内容如下
wireless-wlan {pinctrl-names = "default";pinctrl-0 = <0xeb 0xec>;WIFI,host_wake_irq = <0x40 0x03 0x00>;sdio_vref = <0x708>;wifi_chip_type = "ap6210";compatible = "wlan-platdata";status = "okay";rockchip,grf = <0x20>;# phandle : pointer handle,唯一标识符号,类似于地址/标签,便于调用phandle = <0x1ad>;WIFI,poweren_gpio = <0x40 0x0a 0x00>;};mmc@fe310000 {power-domains = <0x1f 0x1c>;fifo-depth = <0x100>;pinctrl-names = "default";pinctrl-0 = <0x25 0x26 0x27>;clock-names = "biu\0ciu\0ciu-drive\0ciu-sample";cap-sd-highspeed;no-mmc;bus-width = <0x04>;non-removable;resets = <0x08 0x79>;cap-sdio-irq;interrupts = <0x00 0x40 0x04 0x00>;clocks = <0x08 0x1ee 0x08 0x4d 0x08 0x9c 0x08 0x9d>;num-slots = <0x01>;keep-power-in-suspend;no-sd;compatible = "rockchip,rk3399-dw-mshc\0rockchip,rk3288-dw-mshc";status = "okay";disable-wp;reg = <0x00 0xfe310000 0x00 0x4000>;phandle = <0x100>;sd-uhs-sdr104;max-frequency = <0x8f0d180>;reset-names = "reset";};pinctrl {compatible = "rockchip,rk3399-pinctrl";rockchip,pmu = <0x9d>;ranges;rockchip,grf = <0x1f>;wireless-wlan {wifi-host-wake-irq {rockchip,pins = <0x00 0x03 0x00 0xd3>;phandle = <0xe7>;};wifi-enable-h {rockchip,pins = <0x00 0x0a 0x00 0xd2>;phandle = <0xe8>;};};};
不难看出,两个设备树文件的差别还是很大的,后者使用地址/数组来表示具体的属性值,并将设备树中该节点的所有属性列举出,结构上将所有设备节点存放在同一个根节点下,设备“树”名副其实
从模块/设备管理的角度来讲,后者显然是不可取的,各模块在设备树中的关联太强,在修改时很容易出错,但如果是进行分析比对,这无疑会提高效率,免去了在各文件中切换查找的繁琐的步骤,下图为本人wifi成功启用前后的区别,可以明显看出两者区别所在,第一处为模块的硬件地址,都是唯一的,不对wifi是否正常工作产生影响,第二处左侧为将“ap6210”修改为“ap6354”,,修改后重新编译也能够联网,通过上述分析能够得出wifi未能成功启动问题还在设备树上
3 设备树属性及示例
上一小节提到设备树中存在大量属性,在分析/修改设备树时了解这些属性是必要的,网上关于这部分的资料很零散,本人对wifi进行调试时在这方面花费了不少精力,这里以wifi的部分属性为例,总结如何查看属性的用法
-
进入sdk内核设备树示例目录,该目录下有大量设备类型,常见的例如pinctrl、pwm、spi、iic等,我们的wifi使用的是sdio接口,属于mmc,除此之外有些wifi模块还可能使用usb或者pcie接口
~/ws/sdk/kernel/Documentation/devicetree/bindings/
-
找到
mmc
目录进入可以看到大量文件,从文件名不难猜测出文件与设备厂商相关,像atmel、hi、microchip、nvidia、ti等,大家应该都不陌生,我们所使用的wifi模块是正基(AMPAK)不在上述行列中,唯一与之有点关系的只有rockchip,打开rockchip-dw-mshc.yaml
,可以看到如下这段话,大致内容是说rockchip使用的是synopsys(新思)控制器去操作mmc设备,该文件主要是添加了一些rockchip的特有属性,并给出了示例(能力有限,翻译的不准确,可自行查看该文件)title: # 文件名“dw-mshc”与title缩写对应 Rockchip designware mobile storage host controller device tree bindingsdescription: # 文件内容简述 Rockchip uses the Synopsys designware mobile storage host controllerto interface a SoC with storage medium such as eMMC or SD/MMC cards.This file documents the combined properties for the core Synopsys dw mshccontroller that are not already included in the synopsys-dw-mshc-common.yamlfile and Rockchip specific extensions.
-
文件中提到了一个参考文件
“ref: synopsys-dw-mshc-common.yaml#"
,在同级目录下,打开该文件,内容与上一个文件类似,从title: Synopsys Designware Mobile Storage Host Controller Common Properties
这句话可以了解到,这个文件是synopsys的移动存储主机控制器通用属性,可以理解为这个文件中的属性是synopsys的一些特有属性 -
同理,文件中同样提到了一个参考文件
ref: "mmc-controller.yaml#"
,打开这个文件,摘取部分内容如下所示,从描述中可以得知,这个文件的所有属性是mmc设备通用的,不局限于某个厂商或平台,在这个文件中可以找到大多数wifi子节点中的属性,# mmc设备通用控制器 title: MMC Controller Generic Bindingdescription: These properties are common to multiple MMC host controllers. Any hostthat requires the respective functionality should implement them usingthese definitions.It is possible to assign a fixed index mmcN to an MMC host controller(and the corresponding mmcblkN devices) by defining an alias in the/aliases device tree node.
-
在找到这些属性后还剩下最后的工作:修改与使用这些属性,下边列举了三个典型的属性,第一个是bus-width,该属性决定了mmc设备接口的通信硬线数量,类型为枚举,可选参数为1、4和8,如果未显示声明该属性则默认为是单线,king3399中该属性设置的为4
第二个是max-frequency,该属性定义了总线的最大操作频率,数据类型为uint32,实际取值区间为(400000,200000000),我们使用wifi子节点中该参数设置为150000000;
第三个是sd-uhs-sdr104,该属性决定了sdio的传输速度模式,类型为bool(flag),当声明后,表示该设备使用这种传输速度模式,这个属性的具体使用与介绍可参考文末脚注《Rockchip RK3399 - MMC&SD&SDIO基础》
bus-width:description:Number of data lines.$ref: /schemas/types.yaml#/definitions/uint32enum: [1, 4, 8]default: 1max-frequency:description:Maximum operating frequency of the bus.$ref: /schemas/types.yaml#/definitions/uint32minimum: 400000maximum: 200000000sd-uhs-sdr104:$ref: /schemas/types.yaml#/definitions/flagdescription:SD UHS SDR104 speed is supported.
-
通过上面的步骤能够找到大部分关于wifi的属性与用法介绍,然而还是有个别属性无法把握住,例如
num-slots
,网上也没有关于这个属性的介绍,这个就只能靠猜了,从字面意思理解就是SD卡插槽的数量,节点中的赋值是1,而king3399上的SD卡插槽正好是一个,当然这仅仅是个人推测,若是谁手中有多个插槽的板子可以试着看看这个属性是如何使用的
至此,关于wifi的设备树内容已经介绍完毕(由于属性众多,无法逐一列举,可参考上述方法查看具体属性的介绍与用法),下面表格中列举了上述三个文件中的所有属性名
rockchip-dw-mshc.yaml# | synopsys-dw-mshc-common.yaml# | mmc-controller.yaml# | |
---|---|---|---|
compatible | interrupts | $nodename | disable-wp |
reg | resets | #address-cells | wp-gpios |
interrupts | reset-names | #size-cells | no-1-8-v |
clocks | clock-frequency | cap-mmc-highspeed | broken-cd |
clock-names | fifo-depth | cap-sd-highspeed | cd-gpios |
rockchip,default-sample-phase | card-detect-delay | non-removable | wp-inverted |
rockchip,desired-num-phases | data-addr | cd-debounce-delay-ms | cd-inverted |
fifo-watermark-aligned | sd-uhs-sdr12 | bus-width | |
dmas | sd-uhs-sdr25 | max-frequency | |
dma-names | sd-uhs-sdr50 | mmc-ddr-1_2v | |
sd-uhs-sdr104 | mmc-ddr-1_8v | ||
sd-uhs-ddr50 | mmc-ddr-3_3v | ||
cap-power-off-card | cap-sdio-irq | ||
cap-mmc-hw-reset | full-pwr-cycle | ||
disable-cqe-dcmd: | broken-hpi | ||
wakeup-source | compatible | ||
full-pwr-cycle-in-suspend | dsr | ||
mmc-hs400-enhanced-strobe | no-sdio | ||
fixed-emmc-driver-type | no-sd | ||
post-power-on-delay-ms | no-mmc | ||
keep-power-in-suspend | supports-cqe | ||
mmc-hs200-1_2 | vmmc-supply | ||
mmc-hs200-1_8v | vqmmc-supply | ||
mmc-hs400-1_2v | mmc-pwrseq | ||
mmc-hs400-1_8v | reg |
4 wifi部分内核配置
打开网盘中下述路径中的文件,该文件是对wifi部分的使用说明,包含本文前面的设备树部分,但该文件写的比较杂乱,准确来说rp/rk所有的官方文档都写的很差,感觉就像是工程师随手写的笔记,逻辑跳脱,内容陈旧
cdrom_king3399_new\02-软件文档\RK原厂文档\linux\cn\Linux\Wifibt\Rockchip_Developer_Guide_Linux_WIFI_BT_CN.pdf
关于wifi部分的内核配置部分,本人没有心得,仅仅是照着网上的资料看了看配置选项与配置文件,没有做任何修改,下边提到的几个配置文件将在文末提供下载链接,若手中设备wifi有问题可以参考这几个配置文件
首先是查看配置选择,进入~\ws\sdk\kernel
目录,输入make menuconfig ARCH=arm64
,在弹出的界面中进入如下目录
Device Drivers > Network device support > Wireless LAN > Rockchip Wireless LAN support >
本人此处的配置如下,仅供参考,若对某个选项有疑惑可以选择该并按下h
,即可弹出相关的说明,界面中配置选项保存在~\ws\sdk\kernel\.config
文件中,该文件不可手动修改,文件第一行有提到
Rockchip Wireless LAN support
[ ] build wifi ko modules
[*] Wifi load driver when kernel bootup
[ ] Wifi generate random mac......
[*] Broadcom Wireless Device Driver Support --->
Broadcom Wireless Device Driver Support
<*> ap6xxx wireless cards supportEnable Chip Interface (SDIO bus interface support) --->
(/vendor/etc/firmware/fw_bcmdhd.bin) Firmware path
(/vendor/etc/firmware/nvram.txt) NVRAM path
[ ] Enable wlan1 support
此外打开编译日志~\ws\sdk\output\sessions\lastes\xx-kernel-build.log
,可以看到如下一段内容,可以看出~ws\sdk\kernel\arch\arm64\configs\rockchip_wifi_builtin.config
中的部分变量将~ws\sdk\kernel\.config
的变量覆盖了
......
Using .config as base
Merging ./arch/arm64/configs/rockchip_wifi_builtin.config
Value of CONFIG_WIFI_LOAD_DRIVER_WHEN_KERNEL_BOOTUP is redefined by fragment ./arch/arm64/configs/rockchip_wifi_builtin.config:
Previous value: # CONFIG_WIFI_LOAD_DRIVER_WHEN_KERNEL_BOOTUP is not set
New value: CONFIG_WIFI_LOAD_DRIVER_WHEN_KERNEL_BOOTUP=yValue of CONFIG_AP6XXX is redefined by fragment ./arch/arm64/configs/rockchip_wifi_builtin.config:
Previous value: # CONFIG_AP6XXX is not set
New value: CONFIG_AP6XXX=y
......
其中rockchip_wifi_builtin.config的内容如下
# CONFIG_WIFI_BUILD_MODULE is not set
CONFIG_WIFI_LOAD_DRIVER_WHEN_KERNEL_BOOTUP=y
CONFIG_AP6XXX=y
[1] Rockchip RK3399 - MMC&SD&SDIO基础
[2] 正基官网
[3] K3568外接AP6275S WIFI模块调试详解
[4] datasheet(ap6354/ap6210)PWD:wm8e