RV1109+hi3861L hichannel SD卡槽wifi驱动移植

移植平台:瑞芯微RV1109(kernel版本:4.19    SDK:RV1126_RV1109_LINUX_SDK_V1.8.0_20210224)   海思3861L(SDK:Hi3861V100R001C00SPC025 + patch_Hi3861V100C001R001SPC025_for_hichannel_001)

        项目前期没有PCB板,我们只能通过开发板调试外设功能,而RV1109开发板与wifi之间是采用SDIO通讯的,SDIO是高速通讯信号,一般的开发板不会将sdio引出。但是庆幸的是,sd卡也是通过sdio与主控进行通讯的,我们完全可以打一个金手指样式的PCB转接板,将SDIO与wifi模块连接起来,如下图所示:

        hi_channel驱动是基于linux4.9内核编写的,要将该驱动应用至linux4.19内核,则需梳理两个内核版本间的改动对wifi驱动的影响,这对于对内核不熟的小伙伴来说可得花一番功夫了,但不管怎么样,海思已经提供了一版驱动作参考了。下面是在移植过程中总结的修改项,供大家参考:

一、移植遇到的问题(移植修改项)

1. net device结构体成员名称destructor 改为 priv_destructor

报错信息为:

hichannel//oal/oal_net.h:38:57: error: 'oal_net_device_stru' {aka 'struct net_device'} has no member named 'destructor'; did you mean 'priv_destructor'?
 #define oal_netdevice_destructor(_pst_dev) ((_pst_dev)->destructor)
                                                         ^~~~~~~~~~

修改方法:

2. 结构体wait_queue_t 需要改用为 wait_queue_entry_t

报错信息为:

hichannel//oal/oal_wait.h:26:9: error: unknown type name 'wait_queue_t'
 typedef wait_queue_t         oal_wait_queue_stru;
         ^~~~~~~~~~~~

修改方法: 

3. timer用法更改

报错信息为:

/home/disk/fangye/hichannel/oal/oal_timer.h:37:5: error: implicit declaration of function 'init_timer'; did you mean 'init_timers'? [-Werror=implicit-function-declaration]
     init_timer(pst_timer);
     ^~~~~~~~~~
     init_timers
/home/disk/fangye/hichannel//oal/oal_timer.h:39:25: error: assignment to 'void (*)(struct timer_list *)' from incompatible pointer type 'oal_timer_func' {aka 'void (*)(long unsigned int)'} [-Werror=incompatible-pointer-types]
     pst_timer->function = p_func;
                         ^
/home/disk/fangye/hichannel//oal/oal_timer.h:40:14: error: 'oal_timer_list_stru' {aka 'struct timer_list'} has no member named 'data'
     pst_timer->data = ui_arg;

这是因为在linux kernel 4.14版本后,init_timer被移除了,需要换用新的timer_setup接口代替。

参考链接:

https://lwn.net/Articles/735887/

https://stackoverflow.com/a/53842823

修改方法:

hcc_host.c

oal_timer.h

 

 

 

4. 内核调度参数配置

报错信息为:

hichannel//oal/oal_thread.h:59:30: error: storage size of 'st_sched_param' isn't known
     struct sched_param       st_sched_param;
                              ^~~~~~~~~~~~~~

未知st_sched_param的存储大小,说明该变量类型只有声明没有定义,猜测应该是定义到别的头文件中去了。在sdk的kernel driver中搜索sched_setscheduler函数,对比头文件,添加相关的头文件即可。

修改方法:

5. 发送信号函数

hichannel//oal/oal_thread.h:110:5: error: implicit declaration of function 'send_sig'; did you mean 'send_sigio'? [-Werror=implicit-function-declaration]
     send_sig(SIGTERM, pst_thread, 1);
     ^~~~~~~~
     send_sigio
cc1: some warnings being treated as errors
scripts/Makefile.build:333: recipe for target '/home/disk/fangye/projects/rv1109_smart_door/kernel/drivers/hichannel/hcc/hcc_host.o' failed 

同样,在kernel/include下搜索send_sig,包含相应的头文件即可。

修改方法: 

 

6.系统时钟

报错信息为:

hichannel/sdio/sdio_host.c:821:38: error: implicit declaration of function 'cpu_clock'; did you mean 'pud_lock'? [-Werror=implicit-function-declaration]
         hi_sdio->msg[bit].cpu_time = cpu_clock(UINT_MAX);
                                      ^~~~~~~~~
                                      pud_lock
cc1: some warnings being treated as errors
scripts/Makefile.build:333: recipe for target '/home/disk/fangye/projects/rv1109_smart_door/kernel/drivers/hichannel/sdio/sdio_host.o' failed

修改方法:  

添加头文件:

#include <linux/sched/clock.h>

按上述修改项修改后,hi_channel驱动编译通过了:

 

二、平台驱动适配

        由于hi_channel目前只适配了hi3518和君正T31平台,仅仅编译通过还不能正常使用,需要针对不通的平台进行适配。hi3861L是通过sdio与主控通讯为host侧主控提供上网能力的,而hi3861L是一款低功耗wifi模块,为了满足低功耗需求,hi3861L是采用一线SDIO方式进行通讯的。

1. 要适配驱动,首先要适配rv1109的dts

我这里是将sdcard 我这里是基于rv1126-evb-ddr3-v13-tb-emmc.dts进行修改的:

dts配置如下:

Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Change-Id: I59016bc57d21e6459b95d39f2e876daa8a0e2157
---
 arch/arm/boot/dts/rv1109-evb-ddr3-v13-tb-emmc.dts    | 15 +++++++--------
 arch/arm/boot/dts/rv1126-evb-v10.dtsi | 26 +++++++++++++-------------
 arch/arm/boot/dts/rv1126-pinctrl.dtsi |  7 ++++++-
 3 files changed, 26 insertions(+), 22 deletions(-)
 mode change 100644 => 100755 arch/arm/boot/dts/rv1126-evb-v10.dtsi
 mode change 100644 => 100755 arch/arm/boot/dts/rv1126-pinctrl.dtsi

diff --git a/arch/arm/boot/dts/rv1109-evb-ddr3-v13-tb-emmc.dts b/arch/arm/boot/dts/rv1109-evb-ddr3-v13-tb-emmc.dts
index 867b02a..c4da626 100755
--- a/arch/arm/boot/dts/rv1109-evb-ddr3-v13-tb-emmc.dts
+++ b/arch/arm/boot/dts/rv1109-evb-ddr3-v13-tb-emmc.dts
@@ -414,16 +414,15 @@
 };
 
 &sdmmc {
-    bus-width = <4>;
-    cap-mmc-highspeed;
-    cap-sd-highspeed;
-    card-detect-delay = <200>;
+    max-frequency = <50000000>;
+    bus-width = <1>;
+    cap-sdio-irq;
+    keep-power-in-suspend;
     rockchip,default-sample-phase = <90>;
-    supports-sd;
-    sd-uhs-sdr12;
+    supports-sdio;
     sd-uhs-sdr25;
-    sd-uhs-sdr104;
-    vqmmc-supply = <&vccio_sd>;
+    vqmmc-supply = <&vcc3v3_sd>;
+    pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_det &sdmmc0_bus1>;
     status = "okay";
 };
 
diff --git a/arch/arm/boot/dts/rv1126-evb-v10.dtsi b/arch/arm/boot/dts/rv1126-evb-v10.dtsi
old mode 100644
new mode 100755
index 144e9ed..a124f9c
--- a/arch/arm/boot/dts/rv1126-evb-v10.dtsi
+++ b/arch/arm/boot/dts/rv1126-evb-v10.dtsi
@@ -1265,19 +1265,19 @@
     vref-supply = <&vcc_1v8>;
 };
 
-&sdmmc {
-    bus-width = <4>;
-    cap-mmc-highspeed;
-    cap-sd-highspeed;
-    card-detect-delay = <200>;
-    rockchip,default-sample-phase = <90>;
-    supports-sd;
-    sd-uhs-sdr12;
-    sd-uhs-sdr25;
-    sd-uhs-sdr104;
-    vqmmc-supply = <&vccio_sd>;
-    status = "okay";
-};
+//&sdmmc {
+//    bus-width = <4>;
+//    cap-mmc-highspeed;
+//    cap-sd-highspeed;
+//    card-detect-delay = <200>;
+//    rockchip,default-sample-phase = <90>;
+//    supports-sd;
+//    sd-uhs-sdr12;
+//    sd-uhs-sdr25;
+//    sd-uhs-sdr104;
+//    vqmmc-supply = <&vccio_sd>;
+//    status = "okay";
+//};
 
 &sdio {
     max-frequency = <200000000>;
diff --git a/arch/arm/boot/dts/rv1126-pinctrl.dtsi b/arch/arm/boot/dts/rv1126-pinctrl.dtsi
old mode 100644
new mode 100755
index dd83d8f..c555d7a
--- a/arch/arm/boot/dts/rv1126-pinctrl.dtsi
+++ b/arch/arm/boot/dts/rv1126-pinctrl.dtsi
@@ -1310,7 +1310,12 @@
     };
     sdmmc0 {
         /omit-if-no-ref/
-        sdmmc0_bus4: sdmmc0-bus4 {
+        sdmmc0_bus1: sdmmc0-bus1 {
+            rockchip,pins =
+                /* sdmmc0_d0 */
+                <1 RK_PA4 1 &pcfg_pull_up_drv_level_2>;
+        };
+         sdmmc0_bus4: sdmmc0-bus4 {
             rockchip,pins =
                 /* sdmmc0_d0 */
                 <1 RK_PA4 1 &pcfg_pull_up_drv_level_2>,
-- 
2.7.4

配置完成后,重新编译固件烧录,在插入、拔出wifi卡时会有如下打印:

2. GPIO中断配置

首先查看原理图,我们这里是使用的SDMMC_D1来做中断,与hi_3861L的GPIO8相连,确定RV1109的引脚为GPIO1_A5。

将GPIO1_A5换算成GPIO编号为37(GPIOx共32个GPIO,分为A/B/C/D四组,此处为GPIO1,所以前面GPIO0有32个GPIO,A5表示第1组第6个,相加为38,由于序列从0开始,故SDMMC_D1的GPIO编号为37) 

sdio_host.h

sdio_host.c

由于定义了宏开关,我们需要添加相应编译宏配置:

env_config.mk

三、驱动加载测试

 

插入wifi转接卡:

查看wifi打印,确保hi_channel初始化成功。

加载驱动,会有wal_rx_data_proc failed,暂时不用理会。

wifi会有如下打印信息:

在海思提供的hi_channel sdk包中编译出sample_link程序

驱动加载成功后,执行./sample_link &    与hi_3861L建立通讯,获取IP地址,mac地址、网关、dns服务器等信息(自行开发部分代码),运行成功后wal_rx_data_proc failed报错就消失了,具体什么原因没有深入去定位。

测试上网没有问题,就可以开始你的网络应用了(当然这仅仅是个开始,应用到项目中还需要根据应用场景进行调试优化)

上述为个人开发经验总结如果错误还请多多包涵并指出,有疑问可以留言或私信我,一起探讨~

  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 53
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 53
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值