S5pc100平台wifi模块驱动移植分析

时间:2024.3.31

                 S5pc100平台wifi模块驱动移植分析

一、移植环境:

        1、 主机:Ubuntu 10.10发行版

        2、 目标机:FS_S5PC100平台

        3、 交叉编译工具:arm-none-linux-gnueabi-

        4、wifi模块:marvell-8686

        5、内核:linux-2.6.35

---------------------------------------------------------------------

二、在linux下的移植

1. 平台代码修改

内核驱动支持

        因为S5PC100平台上SDIO功能已经支持,所以只需要内核驱动支持marvell-8686即可。

       由于wifi的接口种类有很多种,比如有usb接口wifi,串口接口wifi,sd卡接口wifi,sdio接口wifi,所以在移植wifi驱动时必须确保usb,串口,sd卡的驱动存在,取决于wifi接口的类型。S5pc100开发板上的wifi的接口是sdio接口的,所以在此之前必须移植号sdio接口的驱动。

$ make menuconfig        修改:

[*] Networking support --->

  [*] Wireless --->

       <*> cfg80211 - wireless configuration API

  {*} common routines for IEEE 802.11 drivers

Device Drivers --->

       [*] Network device support --->

         Wireless LAN --->

                <*>Marvell 8xxx Libertas WLAN driver support

                <*> Marvell Libertas 8385/8686/8688 SDIO 802.11b/g cards

       Generic Driver Options --->

                (sd8686.bin sd8686_helper.bin) External firmware blobs to build into the kernel

2. 内核的修改:

wifi的移植依赖于网卡驱动的移植和nand-flash平台的支持,可以参考Linux-2.6.35内核移植—网卡驱动的移植和Linux-2.6.35内核移植——Nand flash 驱动的移植文件arch/arm/mach-s5pc100/mach-smdkc100.c下有内核的分区, 把第2个分区改成8M。因为生成的文件系统太大,大于4M。修改如下(红色字体部分):

static struct mtd_partition s5pc100_nand_part[] = {

        [0] = {

            .name        = "bootloader",

            .size        = SZ_1M,

            .offset        = 0,

        },

        [1] = {

            .name        = "kernel",

            .size        = SZ_1M * 4,

            .offset        = MTDPART_OFS_APPEND,

        },

        [2] = {

            .name        = "rootfs",

            .size        = SZ_8M,

            .offset        = MTDPART_OFS_APPEND,

        },

        [3] = {

            .name        = "usrfs",

            .offset        = MTDPART_OFS_APPEND,

            .size        = MTDPART_SIZ_FULL,

        },

3. 固件的准备

将固件sd8686.bin和sd8686_helper.bin拷贝到linux-2.6.35/firmware下。编译时会自动编译进内核。

$ cp sd8686.bin linux-2.6.35/firmware/$ cp sd8686_helper.bin linux-2.6.35/firmware/$ make zImage

$ sudo cp zImage /tftpboot

由于wifi驱动在运行时需要两个工具,wpa_supplicant和wpa_cli,所以必须先制作这两个工具放到文件系统的bin目录下面。

三,文件系统的制作

1. wpa_suppicant的移植

源码版本选择:

wpa_supplicant-0.7.3

openssl-0.9.8e

[ openssl移植 ]:

  a、补丁安装

      openssl源码编译需要打wpa_supplicant提供的补丁,我们选择的openssl版本为openssl-0.9.8e所以我们需要wpa_supplicant-0.7.3/patches/openssl-0.9.8e-tls-extensions.patch拷贝到openssl源码下。

$ cp wpa_supplicant-0.7.3/patches/openssl-0.9.8e-tls-extensions.patch openssl-0.9.8e/$ cd openssl-0.9.8e              

$ patch -p1 < openssl-0.9.8e-tls-extensions.patch注意:-p1,这里是数字“1”.

b、配置编译安装

$ ./Configure linux-elf-arm -DL_ENDIAN linux:'arm-cortex_a8-linux-gnueabi-gcc' shared --prefix=/home/linux/workdir/wifi/openssl  打开openssl-0.9.8e中Makefile

$ vim Makefile 修改如下:

- CC= cc

+ CC= arm-none-linux-gnueabi-

- AR= ar $(ARFLAGS) r

+ AR= arm-cortex_a8-linux-gnueabi-ar $(ARFLAGS) r

- RANLIB= /usr/bin/ranlib

+ RANLIB= arm-cortex_a8-linux-gnueabi-ranlib编译:

$ make

$ make install[ wpa_supplicant移植 ]:

在/wpa_supplicant-0.7.3/wpa_supplicant目录下

$ cd wpa_supplicant-0.7.3/wpa_supplicant        

a、Makefile修改

$ vim Makefile

修改#ifndef CC

CC=gcc

#endif为CC= arm-none-linux-gnueabi--gcc //自己的交叉编译工具链在

CFLAGS += -I../src

CFLAGS += -I../src/utils

下添加:

CFLAGS += -I/home/linux/workdir/wifi/openssl/include//注意这是你自己安装wpa_supplicant的路径下的include

修改

LIBS += -lssl

为LIBS += -lssl -L/home/linux/workdir/wifi/openssl/lib/

修改

LIBS_p += -lcrypto

LIBS_p += -lcrypto -L/home/linux/workdir/wifi/openssl/lib/

b、编译

$ cp deconfig .config

$ make此处可能出题以下问题:

/usr/bin/ld: skipping incompatible /usr/local/ssl/lib/libssl.so when searching for -lssl

/usr/bin/ld: skipping incompatible /usr/local/ssl/lib/libssl.a when searching for -lssl

/usr/bin/ld: cannot find -lssl

/usr/bin/ld: skipping incompatible /usr/local/ssl/lib/libcrypto.so when searching for -lcrypto

/usr/bin/ld: skipping incompatible /usr/local/ssl/lib/libcrypto.a when searching for -lcrypto

/usr/bin/ld: cannot find -lcrypto

collect2: ld returned 1 exit status

make: *** [wpa_supplicant] Error 1

解决方法如下:

方法1:可能你在修改wpa_supplicant-0.7.3/wpa_supplicant下Makefile的时候,将CC=gcc直接改为CC=arm-cortex_a8-linux-gnueabi-gcc,而没有按上面方式去掉#ifndef CC和#endif这两行。

方法2:需要先编译安装openssl库,确保两个编译都使用统一工具arm-cortex_a8-linux-gnueabi-gcc,这样只要把openssl和wpa_supplicant两个用同一个编译工具编译即可。

方法3:如果已经安装了openssl库,还出现如上问题,建议更新源,卸载后再装,如果有文件信赖关系不对,运行命令:sudo apt-get -f install.

注:方法1,亲测可行。方法2和3是我在移植的时候出现上面问题,在网上搜到的结果,好像不管用,在此帖出,以供参考。

最后,编译

$ make后将生产的wpa_supplicant和wpa_cli拷贝到根文件系统的bin目录下

$ cp wpa_supplicant /source/rootfs/bin

$ cp wpa_cli /source/rootfs/bin2. 文件系统的制作

至此,wifi的驱动工作已经完成。但是想正常的利用wifi来链接网络,还需要配置wifi。

Wifi配置:

$ cd  文件系统     

 a. 在根文件中添加/etc/resolv.conf,域名解析。

$ vim /etc/resolv.conf内容为:

# Generated by NetworkManager

nameserver 192.168.1.1    //你自己的无线路由的DNS

nameserver 8.8.8.8        //此行可不写

b. 在根文件系统/etc下添加wpa_supplicant配置文件wpa_supplicant.conf

$ vim /etc/wpa_supplicant.conf内容为:

# WPA-PSK/TKIP

ctrl_interface=/var/run/wpa_supplicant

network={

ssid="XXXX" #无线路由ssid

key_mgmt=WPA-PSK

proto=WPA

pairwise=TKIP

group=TKIP

psk="XXXXXXXX" #无线路由密码

}c. 创建目录/var/run/wpa_supplicant

$ mkdir /var/run/wpa_supplicant –p

四,wifi模块的测试

启动开发板完成如下操作:

        ● 配置无线网卡ip      

# ifconfig wlan0 192.168.1.200 # ifconfig -a

   ● 配置默认网关

# route add default gw 192.168.1.1        ● 启动wpa_supplicant连接无线网络

# wpa_supplicant -B -iwlan0 -c /etc/wpa_supplicant.conf问题:wifi libertas: problem fetching packet from firmware

解决:网上有好多解决方法,但都不适用我的情况,最后换了一个wifi模块,就好了。大家也可以看看是不是模块的问题。

        ● 查看连接状态

# wpa_cli status

路由器在设置的时候,也要按照上图中对应的参数进行设置,不然下面会ping不通的。       

ping www.linuxidc.com

完成 !


第二篇:wifi驱动分析


Atheros wifi 驱动分析

作者:jingwenyi

时间:2014/7

Ar6003 驱动文档摘要

1、 wmi : wireless module interface //无线模块结构

2、 bmi : bootloader message interface

3、 htc : host target communications

4、 wps:wifi protected setup

5、 CS:connection services module

6、 STA:station

7、 AP:access point

wifi驱动分析

Wireless application : 生产数据和消费数据

Wireless module interface (WMI):host 和target 之间的通信协议

Host/target communications (HTC): 发送和接收数据

Hardware interface (HIF) :调用硬件接口发送和接收数据(这里用的是sdio 接口)

Bootloader message interface (BMI):在wifi芯片启动时通信协议,可以下载bin文件到wifi芯片中。

Ar6000 wifi 驱动分析(AP 模式分析)

代码执行的主要流程

//挂载sdio 驱动到内核和注册网络设备

module_init(__ar6000_init_module);

?__ar6000_init_module

?status = ar6000_init_module();

?status = HIFInit(&osdrvCallbacks);

? status = sdio_register_driver(&ar6k_driver);注册sdio 驱动(这里直接调用的内核sdio协议栈)

?.probe = hifDeviceInserted, //执行驱动的probe 函数

?ret = hifEnableFunc(device, func);

? kthread_create(async_task, //内核开了一个sdio 异步发送数据的进程

? taskFunc = startup_task; //开一个内核进程,执行startup_task 进程

?if ((osdrvCallbacks.deviceInsertedHandler(osdrvCallbacks.context,device)) != A_OK)//调用安装wifi 设备的函数指针ar6000_android_avail_ev,这个函数是在android_module_init中注册的。 ?ar6000_android_avail_ev

?ret = ar6000_avail_ev_p(context, hif_handle);

?ar6000_avail_ev//这个函数指针赋值赋的很曲折首先在ar6000_init_module(void)函数中赋给了osdrvCallbacks.deviceInsertedHandler = ar6000_avail_ev;然后在android_module_init(&osdrvCallbacks);中ar6000_avail_ev_p = osdrvCallbacks->deviceInsertedHandler;赋给了ar6000_avail_ev_p;

? BMIInit();//开始启动wifi模块

?ar->arHtcTarget = HTCCreate(ar->arHifDevice,&htcInfo);//创建htc ,关闭中断

? status = (ar6000_init(dev)==0) ? A_OK : A_ERROR; //

wifi驱动分析

初始化网络设备

? (BMIDone(ar->arHifDevice) != A_OK))//bmi 启动完成

? status = HTCStart(ar->arHtcTarget);//启动htc ,开启中断

?status = DevUnmaskInterrupts(&target->Device);//开启中断, 注册中断处理函数

?HIFUnMaskInterrupt(pDev->HIFDevice);//注册中断处理函数

?ret = sdio_claim_irq(device->func, hifIRQHandler);//注册中断处理函数,中断后就会调用hifIRQHandler 这个处理函数

? if (register_netdev(dev)) //向内核注册网络设备,到此初始化完成。

//产生中断后的代码流程

?hifIRQHandler(struct sdio_func *func) //中断处理函数 (hif.c)

?status = device->htcCallbacks.dsrHandler(device->htcCallbacks.context); //设备处理函数的函数指针

?A_STATUS DevDsrHandler(void *context);这函数是在创建htc 即HTCCreate 函数中填充的:HTCCreate—>DevSetup?htcCallbacks.dsrHandler = DevDsrHandler;(ar6k_events.c)

?status = ProcessPendingIRQs(pDev, &done, &asyncProc);//处理未决事件的函数,在这里会循环处理(ar6k_events.c)

?status = pDev->MessagePendingCallback();这个函数指针也是在HTCCreate 中填充的target->Device.MessagePendingCallback = HTCRecvMessagePendingHandler;(htc_recv.c) ? HTCRecvMessagePendingHandler();

? DO_RCV_COMPLETION(pEndpoint,&container);

? DoRecvCompletion();

? pEndpoint->EpCallBacks.EpRecv(pEndpoint->EpCallBacks.pContext, pPacket);//这个函数指针是在ar6000_init 中填充的connect.EpCallbacks.EpRecv = ar6000_rx; ar6000_rx 是一个非常重要的函数。 ? ar6000_rx(void *Context, HTC_PACKET *pPacket)

//数据发送流程

? ar6000_data_tx(struct sk_buff *skb, struct net_device *dev)

? HTCSendPkt(ar->arHtcTarget, &cookie->HtcPkt);

? return HTCSendPktsMultiple(HTCHandle, &queue);

? HTCTrySend(target, pEndpoint, pPktQueue);

? HTCIssueSend(target, pPacket);

? status = DevSendPacket(&target->Device,

? status = HIFReadWrite(pDev->HIFDevice, //传给了sido 总线

? AddToAsyncList(device, busrequest);//把要发送的数据包加入异步发送队列

? up(&device->sem_async); //获取信号量,用内核进程进行数据发送

? static int async_task(void *param) //发送数据

? __HIFReadWrite();//发送数据

? sdio_writesb();sdio_memcpy_toio();sdio_readsb();sdio_memcpy_fromio();

? down_interruptible(&busrequest->sem_req) != 0 //释放信号量

//中断发送或,接收流程

?HTCRecvMessagePendingHandler

? status = HTCIssueRecv(target, pPacket);//异步接收数据包

? status = HIFReadWrite(pDev->HIFDevice, //命令传给sdio 总线 ?与发送流程相同

//sta 连接流程

? ar6000_rx ();收到连接的命令,此时的ar->arControlEp=ept=1

? wmi_control_rx(arPriv->arWmi, skb);//解析命令

? case (WMI_CONNECT_EVENTID): //连接命令

? status = wmi_connect_event_rx(wmip, datap, len);

? A_WMI_CONNECT_EVENT(wmip->wmi_devt, ev);

? ar6000_connect_event((devt), (pEvt));

? wireless_send_event(arPriv->arNetDev, IWEVREGISTERED, &wrqu, NULL); //向网络层发送事件 wext-core.c

?skb_queue_tail(&dev_net(dev)->wext_nlevents, skb); //wext-core.c

----------------------------------经过网络层的处理-------------------------------------------------------------------- ?sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)// net/socket.c

?err = dev_ioctl(net, cmd, argp); // net/core/dev.c

?return wext_handle_ioctl(net, &ifr, cmd, arg); // net/wireless/wext-core.c

?ret = wext_ioctl_dispatch(net, ifr, cmd, &info,

ioctl_standard_call,

ioctl_private_call); // net/wireless/wext-core.c

?ret = wireless_process_ioctl(net, ifr, cmd, info, standard, private); //net/wireless/wext-core.c ? return dev->netdev_ops->ndo_do_ioctl(dev, ifr, cmd);//这个是在注册网络设备注册的函数.ndo_do_ioctl = ar6000_ioctl,

---------------------------网络层调用驱动层的函数----------------------------------------

? int ar6000_ioctl(); // ioctl.c

? case IEEE80211_IOCTL_SETKEY: //ioctl.c

? ar6000_ioctl_setkey(arPriv, &keydata); //ioctl.c

? status = ar6000_sendkey(arPriv, ik, keyUsage); //ioctl.c

? status = wmi_addKey_cmd()

? status = wmi_cmd_send(wmip, osbuf, WMI_ADD_CIPHER_KEY_CMDID, sync_flag);

//数据传输流程

? ar6000_rx ();收到连接的数据,此时ept=2

? ar6000_deliver_frames_to_nw_stack((void *) arPriv->arNetDev, (void *)skb);

? A_NETIF_RX_NI(skb);

? netif_rx_ni(skb) //将数据传给ip 层

Hostapd 设置ssid

?int main(int argc, char *argv[]); //main.c

?interfaces.iface[i] = hostapd_interface_init(&interfaces, //main.c

?hostapd_setup_interface(iface)) { //main.c

?ret = setup_interface(iface); //hostapd.c

?return hostapd_setup_interface_complete(iface, 0); //hostapd.c

?if (hostapd_driver_commit(hapd) < 0) { // ap_drv_ops.c

?return hapd->driver->commit(hapd->drv_priv);//在driver_ar6000.c 中赋值的.commit = ar6000_commit

?ar6000_commit(void *priv)//driver_ar6000.c

----------------------从应用层通过ioctl 进入驱动层---------------------------------------------------------------

?if (ioctl(drv->ioctl_sock, SIOCSIWCOMMIT, &iwr) < 0) { //在wireless_ext.c 中赋值的

(iw_handler) ar6000_ioctl_siwcommit,

?ar6000_ioctl_siwcommit(struct net_device *dev, // wireless_ext.c

?ar6000_ap_mode_profile_commit(arPriv); //ar6000_dr.c

?wmi_ap_profile_commit(arPriv->arWmi, &p); //wmi.c

?status = wmi_cmd_send(wmip, osbuf, WMI_AP_CONFIG_COMMIT_CMDID,

NO_SYNC_WMIFLAG); //wmi.c

下面我把我分析的ar6003驱动架构图粘出来

wifi驱动分析

更多相关推荐:
Wifi模块全总结

WIFI学习总结12WLAN技术380211协议简述3211概述3380211四种主要物理组件431工作站Station432接入点AccessPoint433无线媒介WirelessMedium434分布式系...

Wifi模块全总结

WIFI学习总结12WLAN技术380211协议简述3211概述3380211四种主要物理组件431工作站Station432接入点AccessPoint433无线媒介WirelessMedium434分布式系...

(模块二)总结与反馈(一)

总结与反馈一班级微软120xx2班姓名区奕其

模块五总结与反馈

模块五总结与反馈1在这个模块中你做了哪些事情答在这个模块中我首先学习了有关多媒体教室和多媒体网络教室的理论知识我认真分析了必选案例有趣的电子称象通过认真阅读我对案例有了深入的理解然后我又认真阅读了几遍案例所涉及...

模块五总结与反馈

模块五总结与反馈1在这个模块中你做了哪些事情答学习了计算机辅助教学模式之操练与练习教学模式个别化学习的概念及特点个别化学习的优点和局限性个别化学习应用过程中的要点多媒体网络教室的功能多媒体网络教室的适用范围教学...

模块五总结与反馈

模块五总结与反馈1在这个模块中你做了哪些事情在这个模块中我首先对相关的理论知识进行了温习与巩固然后带着5个问题仔细地阅读了有趣的电子称象这样案例认真分析了必选案例有趣的电子称象并在班级讨论区中以新帖的方式进行了...

模块五总结与反馈

1在这个模块中你做了哪些事情在本模块我认真阅读了必选案例和可选案例学习了有关的教学组织形式的内容完成了作业并且注册登陆了博客网有了自己的博客2学完本模块后你有哪些收获学完本模块我最大的收获是对于合作学习的组织形...

模块五总结与反馈

模块五总结与反馈1在这个模块中你做了哪些事情答在这个模块中我学习了有关多媒体教室和多媒体网络教室的理论知识我认真分析了必选案例有趣的电子称象通过认真阅读我对案例有了深入的理解然后我又认真阅读了几遍案例所涉及的理...

模块五总结与反馈

模块五总结与反馈1在这个模块中你做了哪些事情你做了哪些事情答在这个模块中我做了一下事情1学习了有关多媒体教室和多媒体网络教室的理论知识2认真分析了必选案例有趣的电子称象通过认真阅读把所涉及的理论知识摘录了下来接...

模块五总结与反馈

模块五总结与反馈1在这个模块中你做了哪些事情答在模块五教学实施学习过程中我在第一次接触这一模块内容之后首先对这一模块的课程进行了浏览由于时间关系第一次是先完成了活动3的内容在博客网注册并创建了自己的博客阳光小屋...

模块五总结与反馈

模块五总结与反馈1在这个模块中你做了哪些事情答模块五的学习过程在活动一必选案例分析中我先阅读了案例知识点导读着重看了教学实施部分的内容然后思考并回答了针对案例生动有趣的电子称象的5个问题最后在课程讨论区发帖在活...

1——4模块总结

1在前面四个模块中您做了哪些事情1在7月1日前三天我就开始了解这次教育技术培训的内容安装了pdf文档阅读器AdobeReader认真学习学员学习指南熟悉网络培训环境2修改了个人密码和个人资料通过修改个人资料详细...

wifi模块全总结(3篇)