大家好,我是三颗芋圆,始于LWIP,陷于TCP/IP,忠于80211。
终于迎来了第一个专题:Wi-Fi模组移植,本次专题将介绍如何在
tina上移植一款Wi-Fi模组,从理论到实操移植XR829详细介绍。
避免篇幅太长,分成了前导篇,理论篇,实践篇。
理论篇
1.原理概述
从整体结构上 Wi-Fi 可以分为设备端(Device)和主机端(Host);设备端主要是数据链路层
的实现和接口管理,主机端主要是应用层和协议层的实现。
模组驱动移植主要所做的工作:供电使能,传输接口适配。
• 供电使能:提供 WiFi 供电,使能操作。如果平台 WiFi 供电通过
电源管理芯片,那么就需要配
置电源管理芯片电源域进行使能 WiFi 的所需电;WiFi 芯片正常工作需要主控 soc 输出使能信
号。
• 传输接口适配:WiFi 通过
通信接口与主控进行连接,常见的通信接口有 SDIO,USB,PCI,SPI
等。通信接口的驱动往往是由主控端提供,平台层需要提供通信接口初始化(如 SDIO 扫
卡)、读、写等函数操作集合。一般情况下由于通信接口都是标准的 Linux API,所以往往模
组原厂已经适配好了读写等操作的接口函数,平台适配可能仅仅需要配置平台差异就好,如选
择使用 SDIO 接口,需要确定选择的 SDIO 卡号、扫卡函数等。
接下来将围绕硬件接线图及 WiFi 工作的硬件条件、WiFi 启动流程进行重点说明,以理清移植模组本质和原理。
1.1 硬件连接简图
这里主要介绍的是 SDIO 通信方式的连接图:
1.2 硬件工作条件
Wi-Fi 模组工作的条件,如下图,需要满足以下几个条件:
•(1)供电:一般有两路供电,其中 VCCWIFI 为主电源,VCCIOWIFI 为 IO 上拉电源。【需要特别留意,有时候设计可以两路电合并】
•(2)使能:要能正常工作,需要 WLREGON 给高电平。【需要特别留意,部分模组可能有时序要求,比如先拉高再拉低,再拉高】
•(3)唤醒主控:当系统休眠时,Wi-Fi 模组可通过 WLWAKEAP 的中断唤醒主控。【需要特别留意,有些模组也通过该引脚来作为主控接收数据的中断】
•(4)SDIO:与 SOC 的通信有通过 USB,SDIO 等,这里以SDIO 为例,其中 SDIO 0~3为 SDIO 的 4 条数据线。
•(5)次时钟 32.768Khz 信号:根据模组而定,有些模组内部通过(6)中的输入的 clk 进行分频得到,有些需要外部单独输入该信号。
•(6)主时钟 24/26Mhz 信号。
1.3 软件启动流程
整体流程分为如下几个阶段:
系统启动-> 驱动加载-> 服务加载-> 启动网卡-> 访问网络
2. 步骤概述
移植适配 Wi-Fi 模组,本小节详细描述移植一款新物料的步骤。总结为五步法,接下来将对其 5
步依次展开叙述。
• 内核驱动适配
• 硬件资源适配
• 方案 module 适配
• 添加 Firmware
• 应用工具适配
相关文件说明:
注:
linux-x.x 代表具体内核版本如:inux-4.9;
ic_xxx 表示具体芯片如:r328,r528;
plat_xxx 表示具体方案如:evb2;
sys_config.fex 和 board.dts 是随着内核版本升级引入的配置文件,路径会有些许改变,不过共功能都一样,都是对设备的配置。具体模组移植时再说明。
2.1 内核驱动适配
内核驱动适配又分为 5 个小步骤:
• 获取源码。
• 添加 Kconfig 和 Makefile 配置。
• 修改驱动源码
• make kernel_menuconfig 配置。
• 编译。
1) 获取驱动源码
在新方案上移植一款 Wi-Fi 模组时,可以先查看《支持列表》文档是否有类似方案支持该模组。
如果没有支持,则需要跟模组原厂获取驱动资料包。拿到原厂提供的资料包需要仔细阅读模组原厂提供的材料,如:支持的通信接口类型 SDIO, 还是 USB;SDIO 是 2.0 还是 3.0;支持 2.4G
还是 5G 甚至是双频等。
2)添加 Kconfig 和 Makefile 配置。
tina/lichee/linux-5.4/drivers/net/wireless/Kconfig 文件中引入 xxx 驱动的 Kconfig 配置
- <span class="hljs-attribute">source</span> <span class="hljs-string">"drivers/net/wireless/xxx/Kconfig"</span>
tina/lichee/linux-5.4/drivers/net/wireless/Makefile 文件中引入 xxx 驱动的 Makefile 配置
- <span class="hljs-meta">obj-[ DISCUZ_CODE_1 ]amp;amp;lt;/span><span class="bash">(CONFIG_RTL8723DS) += xxx/</span>
注:xxx 代办具体驱动型号,如 xr829、rtl8723ds 等
3)修改驱动源码
这一步是很关键的,我们需要定义自己的模组上下电,扫卡接口来对接 Tina 系统提供的接口,以
及原厂提到的关于平台适配的注意事项修改。
Tina 常用接口:
- <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">sunxi_wlan_set_power</span><span class="hljs-params">(<span class="hljs-keyword">bool</span> on)</span></span>; <span class="hljs-comment">//上下电接口,参数0:上电;1:下电</span>
- <span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">sunxi_wlan_get_bus_index</span><span class="hljs-params">(<span class="hljs-keyword">void</span>)</span></span>; <span class="hljs-comment">//获取sdio通信接口的busnum,一般是sdc1</span>
- <span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">sunxi_wlan_get_oob_irq</span><span class="hljs-params">(<span class="hljs-keyword">void</span>)</span></span>; <span class="hljs-comment">//获取中断号</span>
- <span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">sunxi_wlan_get_oob_irq_flags</span><span class="hljs-params">(<span class="hljs-keyword">void</span>)</span></span>; <span class="hljs-comment">//获取中断标志</span>
- <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">sunxi_mmc_rescan_card</span><span class="hljs-params">(<span class="hljs-keyword">unsigned</span> ids)</span></span>; <span class="hljs-comment">//mmc提供的扫卡函数</span>
一般对接过程:
- 上电:
- <span class="hljs-keyword">int</span> platform_wifi_power_on(void)
- {
- <span class="hljs-keyword">int</span> wlan_bus_index = <span class="hljs-number">0</span>;
- sunxi_wlan_set_power(<span class="hljs-number">1</span>);
- mdelay(<span class="hljs-number">100</span>);
- wlan_bus_index = sunxi_wlan_get_bus_index();
- <span class="hljs-keyword">if</span>(wlan_bus_index < <span class="hljs-number">0</span>){
- RTW_INFO(<span class="hljs-string">"get wifi_sdc_id failed
- "</span>);
- <span class="hljs-keyword">return</span> -<span class="hljs-number">1</span>;
- } <span class="hljs-keyword">else</span> {
- RTW_INFO(<span class="hljs-string">"----- %s sdc_id: %d
- "</span>, __FUNCTION_<span class="hljs-number">_</span>, wlan_bus_index);
- sunxi_mmc_rescan_card(wlan_bus_index);
- }
- <span class="hljs-comment">#ifdef CONFIG_GPIO_WAKEUP</span>
- oob_irq = sunxi_wlan_get_oob_ir<span class="hljs-string">q()</span>;
- <span class="hljs-comment">#endif</span>
- <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
- }
- 下电:
- void platform_wifi_power_off(void)
- {
- <span class="hljs-keyword">int</span> wlan_bus_index = <span class="hljs-number">0</span>;
- sunxi_wlan_set_power(<span class="hljs-number">0</span>);
- mdelay(<span class="hljs-number">100</span>);
- RTW_INFO(<span class="hljs-string">"%s: remove card, power off.
- "</span>, __FUNCTION_<span class="hljs-number">_</span>);
- wlan_bus_index = sunxi_wlan_get_bus_index();
- sunxi_mmc_rescan_card(wlan_bus_index);
- }
提供 platform_wifi_power_on() 和 platform_wifi_power_off() 接口给驱动 probe 调用。
注:以上提到的接口对接都是系统平台通用的,可以直接从已经支持的模组中获取适配的文件
- tina/lichee/linux-5.4/drivers/net/wireless/xxx/platform/platform_ARM_SUNxI_sdio.c
2.2 硬件资源适配
1)确认供电方式
模组的供电,我们需要确认的是 VCC-WIFI 和 VCCIO-WIFI 供电的来源,如果两路供电来源来
自电源管理芯片,则需要配置电源管理芯片输出两路电,如果是直接供电,那么就不需要进行软件配置输出。
两路供电来源于 R818 AXP707:
合并一路供电来源于 R329 :
对于 WiFi 和 BT 二合一的模组,供电部分是复用的。分别为 VCC-WIFI 和 VCCIO-WIFI,从R818 原理图来判断,两路电源是由电源管理芯片 DLDO1 和 DLDO4 分别输出;从 R329 原理图来判断,合并一路供电由 DCDC3 直接供电。关于电源管理芯片的驱动原理可参考电源管理驱动使用说明或咨询电源管理芯片驱动开发工程师。通常情况下该部分已经准备好,对于 Wi-Fi开发工程师来说只需要会配置电源输出即可, 配置方法见下 board.dts 中关于 wlan_power、wlan_io_regulator 标识的配置。
2.3 方案 module 适配
1)添加 module 配置文件:
模组一般会编译生成 KO 文件,添加这个配置文件主要是基于 Tina 系统的构建法则,将编译生成的 ko 文件拷贝到文件系统中,同时可以配置驱动是否需要开机启动自加载。示例如下:
- <span class="hljs-keyword">define</span> KernelPackage/net-xr829-40M
- SUBMENU:=<span class="hljs-variable">$(WIRELESS_MENU)</span>
- TITLE:=xr829 support (staging)
- DEPENDS:= +@IPV6
- KCONFIG:=
- CONFIG_XR829_WLAN=m
- FILES:=<span class="hljs-variable">$(LINUX_DIR)</span>/drivers/net/wireless/xr829/wlan/xradio_core.ko
- FILES+=<span class="hljs-variable">$(LINUX_DIR)</span>/drivers/net/wireless/xr829/wlan/xradio_wlan.ko
- FILES+=<span class="hljs-variable">$(LINUX_DIR)</span>/drivers/net/wireless/xr829/umac/xradio_mac.ko
- AUTOLOAD:=<span class="hljs-variable">$(<span class="hljs-built_in">call</span> AutoProbe, xradio_mac xradio_core xradio_wlan)</span>
- <span class="hljs-keyword">endef</span>
- <span class="hljs-keyword">define</span> KernelPackage/net-xr829-40M/description
- Kernel modules for xr829 support
- <span class="hljs-keyword">endef</span>
- <span class="hljs-variable">$(<span class="hljs-built_in">eval</span> $(<span class="hljs-built_in">call</span> KernelPackage,net-xr829-40M)</span>)
module 配置整体分为两个部分,都是固定的格式,第一部分是配置 module 在 menuconfig 中的显示和加载信息,第二部分是 module 的简单描述信息。
具体标签含义如下:
2.4 添加 Firmware
1)添加 firmware 文件:
部分 Wi-Fi 模组工作涉及运行在 devices 端的 firmware 文件【可以简单理解为一些未开源的bin 文件】,添加这个文件主要就是在启动阶段中完成下载的流程,具体 firmware 的原理不用
深入了解。
Tina 上的统一路径为:tina/package/firmware/linux-firmware
2)添加 firmware 配置:
增加 Makefile 文件,配置的主要作用就是基于 Tina 系统的构建法则将 firmware 文件拷贝到系
统对应的目录,为启动流程下载 firmware 做准备。
2.5 应用工具适配
1)iperf
2)wifimanager
3)wpa_supplicant
4)wpa_cli
5)rf 工具
应用工具的配置,主要功能就是借助应用来测试 Wi-Fi 的扫描联网等功能。这一部分在【网络Tips2中有截图介绍,这里就不再贴图了哈。】