海华AW_CM276NF模块驱动调试

基本知识

SD和MMC

SD (Secure Digital) 与 MMC (Multimedia Card) MMC 是较早的一种记忆卡标准,目前已经被 SD 标准取代。 SD 是一种 flash memory card 的标准,也就是一般常见的 SD 记忆卡。

SDIO(Secure Digital I/O)

SDIO 就是 SD 的 I/O 接口的意思。 更具体的说,SD 本来是记忆卡的标准,但是现在也可以把 SD 拿来插上一些外围接口使用,这样的技术便是 SDIO。

SDIO 通过 SD 的 I/O 管脚来连接外部的外围 device 并传输数据。这些外围设备,我们称为 SDIO 卡,常见的有:

  • Wi-Fi card(无线网络卡)

  • CMOS sensor card(照相模块)

  • GPS card

  • GSM/GPRS modem card

  • Bluetooth card

  • Radio/TV card

SDIO 卡 和 SD 卡 的区别

SD卡使用的是SD卡协议,而SDIO卡使用的是SDIO协议! 协议不一样,初始化/读写方式也不一样!

SDIO-Wifi 模块

SDIO-Wifi 模块是基于 SDIO 接口的符合 wifi 无线网络标准的嵌入式模块,内置无线网络协议IEEE802.11协议栈以及TCP/IP协议栈,能够实现用户主平台数据通过SDIO口到无线网络之间的转换。 SDIO 具有传输数据快,兼容SD、MMC接口等特点。

对于SDIO接口的wifi,首先,它是一个sdio的卡的设备,然后具备了wifi的功能。 所以,注册的时候还是先以sdio的卡的设备去注册的。然后检测到卡之后就要驱动他的wifi功能

SDIO 总线

SDIO总线 和 USB总线 类似,SDIO也有两端,其中一端是HOST端,另一端是device端。所有的通信都是由HOST端 发送 命令 开始的,Device端只要能解析命令,就可以相互通信。 CLK信号:HOST给DEVICE的 时钟信号,每个时钟周期传输一个命令。 CMD信号:双向 的信号,用于传送 命令 和 反应。 DAT0-DAT3 信号:四条用于传送的数据线。 VDD信号:电源信号。 VSS1,VSS2:电源地信号。

SDIO 命令

SDIO总线上都是HOST端发起请求,然后DEVICE端回应请求。 SDIO 命令由6个字节组成。

a – Command:用于开始传输的命令,是由HOST端发往DEVICE端的。其中命令是通过CMD信号线传送的。 b – Response:回应是DEVICE返回的HOST的命令,作为Command的回应。也是通过CMD线传送的。 c – Data:数据是双向的传送的。可以设置为1线模式,也可以设置为4线模式。数据是通过DAT0-DAT3信号线传输的。

SDIO的每次操作都是由HOST在CMD线上发起一个CMD,对于有的CMD,DEVICE需要返回Response,有的则不需要。 对于读命令,首先HOST会向DEVICE发送命令,紧接着DEVICE会返回一个握手信号,此时,当HOST收到回应的握手信号后,会将数据放在4位的数据线上,在传送数据的同时会跟随着CRC校验码。当整个读传送完毕后,HOST会再次发送一个命令,通知DEVICE操作完毕,DEVICE同时会返回一个响应。 对于写命令,首先HOST会向DEVICE发送命令,紧接着DEVICE会返回一个握手信号,此时,当HOST收到回应的握手信号后,会将数据放在4位的数据线上,在传送数据的同时会跟随着CRC校验码。当整个写传送完毕后,HOST会再次发送一个命令,通知DEVICE操作完毕,DEVICE同时会返回一个响应

WIFI 模块解析和启动流程

对于 Wifi 模组的 android 上层的分析,这篇文章讲的非常不错: http://blog.csdn.net/ylyuanlu/article/details/7711433 这篇文章将下图蓝色的和绿色的部分讲的非常详细

SDIO 接口驱动

SDIO 接口的 wifi,首先,它是一个 sdio 卡 设备,然后具备了 wifi 的功能,所以 SDIO 接口的 WiFi 驱动就是在 wifi 驱动 外面套上了一个 SDIO 驱动 的外壳。

SDIO 驱动部分代码结构如下

drivers/mmc 下有 mmc卡、sd卡、sdio 卡驱动。

SDIO驱动仍然符合设备驱动的分层与分离思想。

设备驱动层(wifi 设备):

| 核心层(向上向下提供接口)

| 主机驱动层(实现 SDIO 驱动)

我们主要关心 core 目录(CORE 层),其中是媒体卡的通用代码。包括 core.c host.c stdio.c。 CORE 层完成了:

1. 不同协议和规范的实现

2. 为 HOST 层的驱动提供了接口函数

3. 完成了 SDIO 总线注册

4. 对应 ops 操作

5. 以及支持 mmc 的代码 host 目录(HOST 层)是根据不同平台而编写的 host 驱动

Block Diagram

模块工作原理:

无线模块需要在i.MX8MQ主机系统上加载内核驱动程序,并在基于NXP的无线模块上运行固件。当接口总线驱动程序检测到基于NXP的无线模块时,MLAN模块通过接口适配器下载固件二进制文件。NXP Wi-Fi驱动程序从内核中的cfg80211子系统加载到总线驱动程序和网络堆栈之间。NXP内核驱动程序包括一组控件和配置,用于通过以下接口之一与用户空间通信:

SDIO扫描原理:

1、drivers/mmc/core/core.c-->mmc_rescan,在3个频率下扫描设备(400k、300k、200k、100k)

2、dirvers/mmc/core/core.c-->mmc_rescan_try_freq,在扫描前先发个sdio_reset(CMD52)命令,只有sdio设备会有响应,之后按照sdio(CMD5),sd,mmc的顺序扫描,一单扫到立即返回。

  1. 如果成功检测到设备,便会进行后续的mmc_sdio_card和mmc_add_func,进行建立设备节点操作。

/*
 * Starting point for SDIO card init.
 */
int mmc_attach_sdio(struct mmc_host *host)
{
        int err, i, funcs;
        u32 ocr, rocr;
        struct mmc_card *card;
        printk("%s line=%d\n",__FUNCTION__,__LINE__);
        WARN_ON(!host->claimed);
.....
        err = mmc_sdio_init_card(host, rocr, NULL, 0);
        ......
               for (i = 0; i < funcs; i++, card->sdio_funcs++) {
#ifdef CONFIG_MMC_EMBEDDED_SDIO
                if (host->embedded_sdio_data.funcs) {
                        struct sdio_func *tmp;
                        tmp = sdio_alloc_func(host->card);
                } else {
#endif                 
             printk("%s line=%d\n",__FUNCTION__,__LINE__);
                err = sdio_init_func(host->card, i + 1);
                    if (err)
                    goto remove;
            }
        mmc_release_host(host);
        err = mmc_add_card(host->card);
        if (err)
                goto remove_added;
        /*
         * ...then the SDIO functions.
         */
        for (i = 0;i < funcs;i++) {
                err = sdio_add_func(host->card->sdio_func[i]);
                if (err)
                        goto remove_added;
        }
  }

设备树配置:

&usdhc3 {
    pinctrl-names = "default", "state_100mhz", "state_200mhz";
    pinctrl-0 = <&pinctrl_usdhc3>, <&pinctrl_usdhc3_gpio>;
    pinctrl-1 = <&pinctrl_usdhc3>, <&pinctrl_usdhc3_gpio>;
    pinctrl-2 = <&pinctrl_usdhc3>, <&pinctrl_usdhc3_gpio>;
    bus-width = <4>;
    pinctrl-assert-gpios = <&lsio_gpio4 10 GPIO_ACTIVE_HIGH>;

    /*follow is power management features*/
    
    non-removable;
    cap-power-off-card;
    keep-power-in-suspend;
    pm-ignore-notify;
    //enable-sdio-wakeup;
    vmmc-supply = <&reg_usdhc3_vmmc>;//a phandle of a regulator, supplying VCC to the card
    status = "okay";
};
pinctrl_usdhc3: usdhc3grp {
                fsl,pins = <
                      IMX8QM_USDHC3_CLK_CONN_USDHC3_CLK                     0x06000041
                      IMX8QM_USDHC3_CMD_CONN_USDHC3_CMD                     0x00000021
                      IMX8QM_USDHC3_DATA0_CONN_USDHC3_DATA0                 0x00000021
                      IMX8QM_USDHC3_DATA1_CONN_USDHC3_DATA1                 0x00000021
                      IMX8QM_USDHC3_DATA2_CONN_USDHC3_DATA2                 0x00000021
                      IMX8QM_USDHC3_DATA3_CONN_USDHC3_DATA3                 0x00000021
                >;
        };
pinctrl_usdhc3_gpio: usdhc3grpgpio {
        fsl,pins = <
            IMX8QM_USDHC3_RESET_B_LSIO_GPIO4_IO09            0x00000021/*C7*/
            IMX8QM_SAI1_RXFS_LSIO_GPIO3_IO14                0x00000021/*AU3*//*pull-up:low drive strength*/
            IMX8QM_USDHC3_VSELECT_LSIO_GPIO4_IO10            0x00000021/*A7*/
            /*IMX8QM_ADC_IN2_LSIO_GPIO3_IO20                    0x00000021/*AP8*/
        >;
    };

驱动加载和模块配置

驱动源码可以找供应商提供,编译完成后会生成对应文件,我们一般需要用到下面三个文件wifi_mod_para_conf、mlan.ko、maol.ko

把firmware和wifi_mod_para.conf拷贝到firmware搜索目录,这里注意linux一般是/lib/firmware,在这个目录下新建nxp目录,拷贝到/lib/firmware/nxp

Insmod mlan.ko

Insmod maol.ko mod_para=nxp/wifi_mode_para.conf drvdbg=0x0007

加载完成后dmesg的打印信息如下:

[ 466.774446] wlan: Loading MWLAN driver

[ 466.778964] wlan: Register to Bus Driver...

[ 466.783182] sdio_register_driver

[ 466.819410] mmc_sdio_init_card!

[ 466.896334] vendor=0x02DF device=0x9141 class=0 function=1

[ 466.901935] Attach moal handle ops, card interface type: 0x104

[ 466.910810] SD8997: init module param from usr cfg

[ 466.915712] card_type: SD8997, config block: 0

[ 466.920201] cfg80211_wext=0xf

[ 466.923207] wfd_name=p2p

[ 466.925815] max_vir_bss=1

[ 466.929519] cal_data_cfg=none

[ 466.932540] drv_mode = 7

[ 466.935106] ps_mode = 2

[ 466.937556] auto_ds = 2

[ 466.940930] fw_name=nxp/sdiouart8997_combo_v4.bin

[ 466.946629] SDIO: max_segs=128 max_seg_size=65535

[ 466.951450] rx_work=1 cpu_num=6

[ 466.954778] Attach mlan adapter operations.card_type is 0x104.

[ 466.955339] wlan: Enable TX SG mode

[ 466.955344] wlan: Enable RX SG mode

[ 466.958087] Request firmware: nxp/sdiouart8997_combo_v4.bin

[ 467.732864] Wlan: FW download over, firmwarelen=571312 downloaded 571312

[ 468.485944] WLAN FW is active

[ 468.488922] on_time is 468383133090

[ 468.532213] fw_cap_info=0x181c3fa3, dev_cap_mask=0xffffffff

[ 468.532242] max_p2p_conn = 8, max_sta_conn = 8

[ 468.539156] wlan: mlan0 set max_mtu 2000

[ 468.548440] wlan: uap0 set max_mtu 2000

[ 468.558506] wlan: p2p0 set max_mtu 2000

[ 468.565702] wlan: version = SD8997----16.92.21.p41-MM5X16322.p3-(FP92)

[ 468.577914] wlan: Register to Bus Driver Done

[ 468.582313] wlan: Driver loaded successfully

无线配置

驱动正常加载后ifconfig可以查看模块信息

ifconfig -a

mlan0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500

inet 192.168.1.110 netmask 255.255.255.0 broadcast 192.168.1.255

ether b4:8c:9d:0d:88:d3 txqueuelen 1000 (Ethernet)

RX packets 0 bytes 0 (0.0 B)

RX errors 0 dropped 0 overruns 0 frame 0

TX packets 0 bytes 0 (0.0 B)

TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

p2p0: flags=4098<BROADCAST,MULTICAST> mtu 1500

ether b6:8c:9d:0d:88:d3 txqueuelen 1000 (Ethernet)

RX packets 0 bytes 0 (0.0 B)

RX errors 0 dropped 0 overruns 0 frame 0

TX packets 0 bytes 0 (0.0 B)

TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

uap0: flags=4098<BROADCAST,MULTICAST> mtu 1500

ether b4:8c:9d:0d:89:d3 txqueuelen 1000 (Ethernet)

RX packets 0 bytes 0 (0.0 B)

RX errors 0 dropped 0 overruns 0 frame 0

TX packets 0 bytes 0 (0.0 B)

TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

使用wpa配置无线网络

1、配置和连接无线只需要修改/etc/wpa_supplicant/test.confg

ctrl_interface=/var/run/wpa_supplicant
update_config=1
 network={
       ssid="HR-office" /*wifi热点*/
       key_mgmt=WPA-PSK 
       psk="hairoutech@2020" /*wifi热点密码*/
}

2、设置mlan0的ip:ifconfig mlan0 172.18.150.30 netmask 255.255.255.0 up

3、连接到AP:wpa_supplicant -D nl80211 -i mlan0 -c /etc/wpa_supplicant/HR-office.conf &

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值