我是靠谱客的博主 瘦瘦缘分,最近开发中收集的这篇文章主要介绍MTK BT/WIFI小析,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

闲的时候查阅了MTK BT/WIFI相应资料,了解了一点框架知识,并且对底层驱动做了简单的代码流程跟踪,也留有一些问题,现做简单记录,不确定以后是否还有时间和机会再继续完善。




下图是MT6589平台,SDIO接口的硬件电路图,该平台有四组SDIO,其中MT6520/28会用到其中一组,当然SDIO仅用于WIFI的数据通信。








在init.project.rc文件,

mknod/dev/stpbt  c 192 0;

insmod/system/lib/modules/mtk_hif_sdio.ko

查看生成mtk_hif_sdio.ko的MakeFile文件,从而可以找到对应的源文件,

obj-$(CONFIG_MTK_COMBO) += mtk_hif_sdio$(EXT_FLAG).o

mtk_hif_sdio$(EXT_FLAG)-objs    := linux/pub/hif_sdio.o

mtk_hif_sdio$(EXT_FLAG)-objs    += linux/pub/hif_sdio_chrdev.o

mtk_hif_sdio$(EXT_FLAG)-objs    += platform/alps/mtk_wcn_cmb_hw.o

mtk_hif_sdio$(EXT_FLAG)-objs    += platform/alps/wmt_plat_alps.o

mtk_hif_sdio$(EXT_FLAG)-objs    += linux/pub/osal.o

模块入口:

mediatekkerneldriverscombocommonlinuxpubhif_sdio.c


同理,可得到如下结果,

insmod/system/lib/modules/mtk_stp_wmt.ko

# WMT DRIVER

obj-$(CONFIG_MTK_COMBO) += mtk_stp_wmt$(EXT_FLAG).o

# WMT DRIVER-core part

mtk_stp_wmt$(EXT_FLAG)-objs     := core/wmt_core.o core/wmt_ctrl.o  core/wmt_func.o core/wmt_ic_6620.ocore/wmt_lib.o core/wmt_conf.o

 

#ifeq ($(MTK_COMBO_CHIP), MT6628)

mtk_stp_wmt$(EXT_FLAG)-objs     += core/wmt_ic_6628.o

#endif

# WMT DRIVER-linux private part

mtk_stp_wmt$(EXT_FLAG)-objs     += linux/pri/wmt_dev.o linux/pri/wmt_exp.o

mtk_stp_wmt$(EXT_FLAG)-objs     += linux/pri/wmt_tm.o

 

# WMT DRIVER-OSAL

mtk_stp_wmt$(EXT_FLAG)-objs     += linux/pub/osal.o

# WMT DRIVER-platform implementation

ccflags-y += -D WMT_PLAT_ALPS

mtk_stp_wmt$(EXT_FLAG)-objs     += platform/alps/wmt_plat_alps.o

mtk_stp_wmt$(EXT_FLAG)-objs     += platform/alps/wmt_plat_stub.o

 

# FIXME: select desired hw according to projectconfiguration

#ifeq ($(MTK_COMBO_CHIP), MT6628)

#mtk_stp_wmt$(EXT_FLAG)-objs    += platform/alps/mtk_wcn_cmb_hw_6628.o

#else

mtk_stp_wmt$(EXT_FLAG)-objs     += platform/alps/mtk_wcn_cmb_hw.o

#endif

 

mtk_stp_wmt$(EXT_FLAG)-objs     += linux/pri/stp_exp.o core/stp_core.ocore/psm_core.o core/btm_core.o linux/pri/stp_dbg.o

#ifeq ($(MTK_COMBO_CHIP), MT6628)

# WMT stub part (built-in kernel image)

obj-y                  += platform/alps/mtk_wcn_cmb_stub_alps.o

#endif

模块入口为:mediatekkerneldriverscombocommonlinuxpriwmt_dev.c

 

insmod/system/lib/modules/mtk_stp_uart.ko

mediatekkerneldriverscombocommonlinuxpristp_uart.c

 

insmod/system/lib/modules/mtk_stp_bt.ko

mediatekkerneldriverscombocommonlinuxpubstp_chrdev_bt.c


hif_sdio.c文件简单分析

hif_sdio_init:


第1794行,注册sdio总线上的驱动mtk_sdio_client_drv,

sdio总线上驱动与设备匹配时通过mtk_sdio_id_tbl来配对。

而对的sdio_func设备,由host给设备上电,识别等一系列动作找到并生成。

hif_sdio_probe函数:找到对应的sdio_func后,加入list表;使能该func,设置host与之通信时最大的数据传输buf。

enables a SDIO functionfor usage


SDIO设备的识别过程大概如下,

kerneldriversmmccorehost.c

mmc_alloc_host函数中INIT_DELAYED_WORK(&host->detect,mmc_rescan);

mmc_rescan ----> mmc_rescan_try_freq ---->mmc_attach_sdio

如果有时间可以继续了解Mtk host 的实现代码及host->detect调用。


回到hif_sdio_init函数,第1798行,调用hifsdiod_start函数,

创建consys-id-query线程,每10s运行一次,还不明白这样做的目的是什么?


回到hif_sdio_init函数,第1800行,调用hif_sdio_create_dev_node函数

创建hifsdiod字符设备,获取ChipId。


WMT驱动

mediatekkerneldriverscombocommonlinuxpriwmt_dev.c

WMT_init函数,



第1680行,调用stp_drv_init,主要是初始化stp_core_ctx结构体。

第1682~1696行,注册mtk_stp_wmt字符设备,mknod /dev/stpwmt c 190 0;即其设备为/dev/stpwmt


后续会简单跟踪BT数据的简单流程,在BT驱动加载后,会生成/dev/stpbt设备文件,mtk 库文件中的操作函数,通过对内核stpbt设备文件进行操作控制。


BT

mediatekkerneldriverscombocommonlinuxpubStp_chrdev_bt.c

注册mtk_stp_BT_chrdev字符设备,而BT_DEV_MAJOR为192,在init.project.rc: mknod /dev/stpbt  c 192 0;故该字符设备为/dev/stpbt,对应的设备操作如下:

BT_open:

mtk_wcn_wmt_func_on(WMTDRV_TYPE_BT)->mtk_wcn_wmt_func_ctrl(WMTDRV_TYPE_BT,WMT_OPID_FUNC_ON); 即发送(WMTDRV_TYPE_BT,WMT_OPID_FUNC_ON)的消息给处理中心,

第81行从gDevWmt.rFreeOpQ.queue数组中获取P_OSAL_OP,

gDevWmt.rFreeOpQ.queue队列在

mediatekkerneldriverscombocommoncorewmt_lib.c:wmt_lib_init函数中由gDevWmt.arQue完全填充,如下代码所示,

第98行,wmt_lib_host_awake_get ->wmt_plat_wake_lock_ctrl(WL_OP_GET);如下面代码所示,

根据counter是否大于0来加/解睡眠锁wmtWakeLock。

第100行,DISABLE_PSM_MONITOR ->wmt_lib_ps_disable ->mtk_wcn_stp_psm_disable

mtk_wcn_stp_is_uart_fullset_mode判断是否为MTKSTP_UART_FULL_MODE

  STP_SET_SUPPORT_PROTOCOL <- mtk_wcn_stp_set_mode <-wmt_ctrl_stp_conf_ex <-

wmt_ctrl_stp_conf 对应函数指针数组wmt_ctrl_func中的WMT_CTRL_STP_CONF数据成员,<- wmt_ctrl <-

mt6628_sw_init <- wmt_ic_ops_mt6628 <-wmt_core_hw_check 对应的操作入口保存在gMtkWmtCtx.p_ic_ops。

opfunc_pwr_on -> wmt_core_stp_init

mediatekkerneldriverscombocommoncorewmt_lib.c:wmtd_thread消息队列转发机制处理中心,

由WMT_init -> wmt_lib_init创建。

mtk_wcn_stp_is_ready判断stp是否ready

第106行,wmt_lib_put_act_op将P_OSAL_OP加入rActiveOpQ队列,唤醒消息处理线程,并等待处理结果的返回。

处理流程:

    pOp->op.opId= WMT_OPID_FUNC_ON;

pOp->op.au4OpData[0]= WMTDRV_TYPE_BT;

wmt_core_opid-> wmt_core_opid_handler -> opfunc_func_on ->

iRet= (*(gpWmtFuncOps[drvType]->func_on))(gMtkWmtCtx.p_ic_ops,wmt_conf_get_cfg()); ->

wmt_func_bt_ops-> wmt_func_bt_on -> wmt_core_func_ctrl_cmd(WMTDRV_TYPE_BT,MTK_WCN_BOOL_TRUE);该函数代码如下,

wmt_core_tx -> wmt_ctrl_tx_ex ->mtk_wcn_stp_send_data(pData, size, WMT_TASK_INDX);

-> stp_send_tx_queue(stp_core_ctx.sequence.txseq);->

(*sys_if_tx)(&stp_core_ctx.tx_buf[tx_read],last_len, &ret);

sys_if_tx函数指针在mtk_wcn_stp_init函数中赋值,从stp_drv_init函数中可得知对应的函数为mtk_wcn_sys_if_tx,其代码如下,

stp_uart_if_tx由stp_uart_tty_open函数调用mtk_wcn_stp_register_if_tx赋值为mtk_wcn_uart_tx,即最终的数据由uart发送出去。

后续uart是怎么确定哪个及如何衔接数据调用流程,还是继续分析。


mtk_wcn_wmt_msgcb_reg(WMTDRV_TYPE_BT, bt_cdev_rst_cb)


WIFI



最后

以上就是瘦瘦缘分为你收集整理的MTK BT/WIFI小析的全部内容,希望文章能够帮你解决MTK BT/WIFI小析所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(317)

评论列表共有 0 条评论

立即
投稿
返回
顶部