【分享】iTOP4412开发板-Bluetooth移植文档

topeet 发布于 2015/07/20 16:14
阅读 601
收藏 0

本文转自迅为:http://www.topeetboard.com

     近期需要把Bluetooth移植到iTOP-4412 开发平台,查阅了相关资料,经过一段时间的研究、调试,终于成功的将蓝牙功能移植到了开发板上面,这里笔者记录移植过程及注意事项,方便以后工作需要。

 

    iTOP-4412开发板的Bletooth模块与板卡之间的连接采用UART接口,Bletooth硬件模块使用的是MTKMT6620芯片,MTK提供了Android4.0Android4.4driver, Porting Guid,有了这些就为我们的移植工作做了总体性的指导。

 

    但是仅仅有MTK提供的文档还是远远不够的,毕竟硬件接口定义不同,kernel版本也不同,Android层与MTK提供的代码也有差异,这就需要我们在MTK文档的指导下, Step  by Step 进行 Porting 工作.

 

 

移植环境:

    1  iTOP-4412 精英版 +  MT6620 Bletooth模块

    2  kernel  3.0.15  version

    3  Android4.4

    4  Ubuntu12.04  64BIt 开发环境

目录

 

目录 1

1.1  概述 1

1.2  硬件相关部分 2

1.3  Kernel 4

1.3.1 概述 4

1.3.2 代码修改 5

1.4  用户态空间 8

1.5  HAL层移植 9

1.5.1  Bluedroid 10

1.5.2  init.connectivity.rc 文件 12

1.5 总结 12

 

 

1.2  硬件相关部分

 由于MT6620 芯片集成了BluetoothWiFi, FMGPS功能,所以Bluetooth的原理图可查看 MT6620 WiFi原理图部分,下图为Bletooth模块与开发板连接的引脚定义,通过该接口可以知道Bluetooth模块与CPU的交互接口.

 

 

 

 ▆  UART 串口: BluetoothCPU之间的通信接口,命令和数据的传输都是经过串口交换的。另外MT6620固件补丁的下载也是通过串口进行的,所以说串口是必不可少的硬件接口。上图中 Pin8Pin10 为串口部分,与CPU的串口0连接.

 

 ▆ MT6620 芯片使能引脚:  Pin16  PMU_EN ,使能引脚,默认低电平状态,高电平有效启用蓝牙功能之前需要先使能该引脚,这样MT6620才开始工作。

 

 ▆ 中断引脚:Pin 14  BGF_INT , Blutooh, GPS,FM共用的中断引脚,用于告知CPU有数据来了,或者说有请求到了.

 

▆  复位引脚: Pin15 WiFi_RESET ,该引脚与MT6620SYSRST_B连接,用于芯片的复位操作.

 

▆ 芯片工作电压:Pin12提供1.8V的电压输入,Pin19提供3.3VPin20提供5V电压输入.

 

 

 

 

 

下图为MT6620模块原理图部分:

 

 

 

MT6620的引脚定义如下:

 

 

 

 

  以上是进行Porting前的准备工作,当然需要万用表,示波器工具进行辅助的检测,查看Bluetooth模块的工作电压是否正常,GPIO的当前状态,串口的数据波形.

 

   另外需要强调的是,MT6620 Bluetootch支持蓝牙4.0规范,蓝牙4.0规范包括常规蓝牙,高速蓝牙,还有很重要的低功耗蓝牙,即BLE的支持,下面是MT6620蓝牙特性:

 

▆ 支持Bluetooth V2.1 +EDR

▆ 支持Bluetooth 3.0+HS compliance

▆ 支持Bluetooth V4.0 Low Energy (LE)

▆ 使用UART / PCM 接口

▆ 模組包含PA with 13 dBm (class 1) transmit power

▆ Better WiFi/BT coexistence performance

▆ Low power scan function to reduce the power consumption in scan modes 

 

关于MT6620的更多硬件特性,请参考MTK官方发布的MT6620硬件使用指导相关文档.

 

1.3  Kernel

1.3.1 概述

    iTOP4412开发板采用的内核是Linux 3.0.15 版本,MTK官方给的移植Porting没有说明针对具体的 kernel版本,由于是Android4.4,所以kernel应该是3.0以后的版本或者更高支持;

 

   首先按照PoringGuid的指导说明,把NewModify文件夹下面关于kernel部分的修改放到我们的kernel代码里面, 把MT6620的驱动放在driver/misc/目录下面,文件夹名称 mediatek,里面存放的是WMT,既wireless manage tools, 里面提供了与MT6620  download  firmware patch enable /disable MT6620芯片,power on, power off操作的相关驱动部分SDIO总线设备接口驱动Host Interface drivers. 蓝牙驱动mtk_stp_bt.ko 的源码也在这个目录下面,我们以驱动库 .ko 的形式编译驱动模块

 

driver/misc/mediatek/ 库文件列表如下::

 

mtk_hif_sdio.ko ----mmc总线相关接口,mmc总线发现SDIO设备,分配总线地址后,会与该驱动进行适配.适配成功后该驱动会调用WiFi网络驱动,另外Bluetooth也使用了该驱动库文件提供的相应接口;

mtk_stp_uart.ko-----串口相关驱动,通过串口下载固件补丁,设置芯片参数;

mtk_stp_wmt.ko-----core 部分,提供Bluetooth上电,断电,PSM省电管理操作等

mtk_stp_bt.ko ----字符设备驱动,创建Bluetooth设备节点用于与用户空间交互

 

 

 

另外这里附一张Blutooth Kernel层驱动层次图:

  

 

   上图红色部分 BlueZ, Hci_stp.koAndroid4.0 Bluetooth使用的蓝牙协议栈与Kernel库文件。蓝色部分Bluedroid, mtk_stp.bt.ko Android4.4 版本使用的蓝牙协议栈与kernel库文件。Android4.0Android4.4关于Bluetooth部分变化比较大,请大家移植过程中注意这一点,他们之间的具体差异这里不再讲解。

 

  从上图可以看到 bluetooth驱动调用关系:

 

   mtk_stp_bt.ko -> mtk_stp_wmt.ko -> mtk_stp_uart.ko -> uart driver

 

  最后最底层的串口驱动负责蓝牙命令,数据的发送与接收.

 

1.3.2 代码修改

 

1  根据硬件连接情况配置必要的平台资源

 

 修改文件:  kernel/iTop4412_Kernel_3.0/arch/arm/mach-exynos/mach-itop4412.c

 

 关键函数该函数配置MT6620相关的GPIO引脚为初始化输出状态,或者配置为中断状态,Bluetooth驱动会改变这些引脚的状态,这里仅仅是初始化.

 

 

static void __init mtk_combo_init(void)

    {

 

        //MT66XX PMUEN

        if(gpio_request(EXYNOS4_GPC1(0), "GPC1_0"))

        {

                printk(KERN_ERR "failed to request GPC1_0 for MT6620  PMUEN control\n");

        }

        //MT66XX SYSRST

        if(gpio_request(EXYNOS4_GPC1(1), "GPC1_1"))

        {

       printk(KERN_ERR "failed to request GPC1_1 for MT6620  SYSRST control\n");

 

        }

        s3c_gpio_cfgpin(EXYNOS4_GPC1(0), S3C_GPIO_OUTPUT);

        s3c_gpio_cfgpin(EXYNOS4_GPC1(1), S3C_GPIO_OUTPUT);

 

        gpio_direction_output(EXYNOS4_GPC1(0), 0);

        gpio_direction_output(EXYNOS4_GPC1(1), 0);

 

 

        gpio_free(EXYNOS4_GPC1(0));

        gpio_free(EXYNOS4_GPC1(1));

 

        mdelay(5);

 

        //need config eint models for Wifi & BGA Interupt

        if (gpio_request(EXYNOS4_GPX2(5), "WiFi INT"))

                printk(KERN_WARNING "MT6620 WiFi INT(GPX2.5) Port request error!!!\n");

        else    {

                s3c_gpio_setpull(EXYNOS4_GPX2(5), S3C_GPIO_PULL_NONE);

                s3c_gpio_cfgpin(EXYNOS4_GPX2(5), S3C_GPIO_SFN(0xF));

                gpio_free(EXYNOS4_GPX2(5));

        }

 

        if (gpio_request(EXYNOS4_GPX2(4), "BGF INT"))

                printk(KERN_WARNING "MT6620 BGA INT(GPX2.4) Port request error!!!\n");

        else    {

                s3c_gpio_setpull(EXYNOS4_GPX2(4), S3C_GPIO_PULL_NONE);

                s3c_gpio_cfgpin(EXYNOS4_GPX2(4), S3C_GPIO_SFN(0xF));

                gpio_free(EXYNOS4_GPX2(4));

        }

 

        //normal it is high level

        if (gpio_request(EXYNOS4_GPX3(2),  "6260_GPIO2")!=0) {

             printk("[mt6620] ERROR:Cannot request 6260_GPIO2\n");

         } else {

             gpio_direction_output(EXYNOS4_GPX3(2), 1);/* WLAN_CHIP_PWD */

             gpio_set_value(EXYNOS4_GPX3(2), 1);

             mdelay(100);

             gpio_free(EXYNOS4_GPX3(2));

}

 

    return; }

 

关键结构体该结构体告诉MT6620驱动相关部分使用了平台的哪些GPIO资源.

结构体所属文件: kernel/iTop4412_Kernel_3.0/arch/arm/mach-exynos/mach-itop4412.c

 

  static struct mtk_wmt_platform_data mtk_wmt_pdata = {

        .pmu =EXYNOS4_GPC1(0), //RK30SDK_WIFI_GPIO_POWER_N,//RK30_PIN0_PB5, //MUST set to pin num in target system

        .rst = EXYNOS4_GPC1(1),//RK30SDK_WIFI_GPIO_RESET_N,//RK30_PIN3_PD0, //MUST set to pin num in target system

        .bgf_int=EXYNOS4_GPX2(4), //IRQ_EINT(20),//RK30SDK_WIFI_GPIO_BGF_INT_B,//RK30_PIN0_PA5,//MUST set to pin num in target system if use UART interface.

        .urt_cts = -EINVAL, // set it to the correct GPIO num if use common SDIO, otherwise set it to -EINVAL.

        .rtc = -EINVAL, //Optipnal. refer to HW design.

        .gps_sync = -EINVAL, //Optional. refer to HW design.

        .gps_lna = -EINVAL, //Optional. refer to HW design.

    };

    static struct mtk_sdio_eint_platform_data mtk_sdio_eint_pdata = {

        .sdio_eint = EXYNOS4_GPX2(5),//IRQ_EINT(21) ,//RK30SDK_WIFI_GPIO_WIFI_INT_B,//53, //MUST set pin num in target system.

    };

    static struct platform_device mtk_wmt_dev = {

        .name = "mtk_wmt",

        .id = 1,

        .dev = {

        .platform_data = &mtk_wmt_pdata,

        },

    };

    static struct platform_device mtk_sdio_eint_dev = {

        .name = "mtk_sdio_eint",

        .id = 1,

        .dev = {

        .platform_data = &mtk_sdio_eint_pdata,

        },

    };

    MTK 官方移植文档中会告诉我们需要在原始内核代码里面增加哪些文件,如何在make menuconfig中配置相关部分,这里就不再详细描述.

 

注意:蓝牙驱动虽然没有使用到mmc总线,但是mtp_hif_sdio.ko 驱动导出了接口函数,mtk_stp_wmt.ko 核心驱动库会调用导出函数,所以mtp_hif_sdio.ko需要加载到内核空间,如果您的产品中不含有WiFi, 仅仅需要Bluetooth功能,那么完全可以不用配置MMC总线部分,不影响蓝牙的使用,但是务必加载mtp_hif_sdio.ko文件。

 

   另外MT6620 具备功耗控制功能,默认情况下如果MT6620 处于idle空闲状态,空闲时间大于60秒后,会自动进入sleep状态,有中断触发时会唤醒,继续工作,您可以使用 "echo 0 0  > /proc/driver/wmt_dbg "命令关闭功耗控制,这样MT6620会始终不会进入sleep状态。另外也可以修改MT6620 mtk_stp_wmt.ko驱动中的参数,更改ide  to  sleep的时间.

 

    MTK 官方提供的驱动代码中芯片默认 idle   5 秒后会进入sleep  状态,使用蓝牙接收文件时,如果用户响应时间超过了5秒(用户没有单击接收或者拒绝按钮),MT6620会休眠,驱动会导致MT6620会进入RESET状态,从而Bluetooth服务会出现问题,Bluetooth功能不可使用,为了避免这样的问题发生,我们把休眠时间由默认的 5秒调整到了60 秒,给用户足够多的响应时间,用户在60秒内 接收或者拒绝蓝牙手机发给板卡的文件,另外文件接收完成后,需要单击状态栏中的文件接收完成提示,尽量在Android4.4 状态栏中不含有关于蓝牙消息的提醒。

u

1.4  用户态空间

下面我们描述一下采用Linux系统和Android系统的用户都需要注意的地方:

 

   驱动层移植完成后, MTKPorting Guid会告诉你需要在用户态运行wmt_launcher工具,作为后台的一个服务程序运行,该服务会配置串口的工作参数,下载固件补丁到MT6620中,他的源代码相对比较简单,只有一个.c文件:

 

原始文件位于MTK发布包:

APEX_Android_4.4_MP_SW_package_V2.0/APEX_Android_4.4_MP_001_panda_combo_mt66xx_Package_Common/New/hardware/mediatek/wmt/stp_uart_launcher.c

 

修改后的文件位于iTOP-4412 Android4.4发布包:

 iTop4412_KK4.4/hardware/mediatek/wmt/stp_uart_launcher.c

 

修改点主要在串口参数配置上,由于内核版本不同,串口设置参数也略有不同.

具体修改可以使用代码比对工具进行比较。

 

    另外需要说明的是运行wmt_launcher的运行参数 跟MTK给的移植文档有点不同,Porting Guid 里面推荐串口波特率使用921600, 而在iTOP-4412的板子上面采用该值会工作不正常,导致固件补丁无法下载,开始怀疑板卡不支持该波特率,后使用串口测试工具专门针对这个串口进行921600测试,也没发现问题,后没有继续查找,而是运行wmt_launcher时采用115200波特率:

 

wmt_launcher  -b 115200  -d  /dev/ttySAC0  -p  /system/etc/firmware &

 

 

注意:  如果您的操作系统使用的是Linux而不是Android,需要修改stp_uart_launcher.c

原始代码里面有Android特有的属性相关部分,Linux系统不具有这个特性,我们提供了修改好的文件:stp_uart_launcher-linux-ok.c ,用户可以作为参考,该文件与原始文件stp_uart_launcher-ori.c,及正常工作的文件 stp_uart_launcher.c 位于相同目录下面.

 

   无论是Linux系统还是Android系统,挂载根文件系统以后需要运行 wmt_launcher 服务,该服务在后台运行,打开 /dev/ttySAC0 串口,监控着串口上报的事件,对事件进行响应,比如内核上报 "下载固件补丁事件,那么wmt_launcher会打开  /system/etc/firmware下面的固件补丁,然后下载到MT6620模块中,该服务不可以被用户终止运行.

1.5  HAL层移植

BluetoothHAL层主要有 Bluedroid 协议栈与MT6620 vendor提供底层库文件组成。

 

 

 

 

    需要我们重点关注的有 bluetooth.default.so  该动态库文件提供了 Framework层调用HAL层的 API 接口,同时向下调用 libbt-hci.so 。  

 

 bluetooth.default.so包含两个静态库:libbt-brm_stack.a   libbt-brm_bta.a .  libbt-brm_stack.a提供Bluetooth  各种profiles的支持比如  a2dp,hid,pan 等等, libbt-brm_bta.a   用于与framdwork层进行通信.

 

 libbt-hci.so 该动态库提供bluetooth.default.so的底层支持,另外他会调用 libbt-vendor.so 接口,

 

通过串口发送,接收命令,数据的操作也是通过该动态库实现的。他位于bluedroid源码目录

 hci 文件夹下。

 

libbt-vendor.so 厂商库文件,用于实现厂商提供的蓝牙模块特性支持,库文件位于android4.4/iTop4412_KK4.4/hardware/mediatek/bt/combo_mt66  目录下。

1.5.1  Bluedroid

    从Android 4.2开始,Bluetooth stack发生了重大改变:从Bluez换成了由GoogleBroadcom联合开发的Bluedroid(当然,核心的部分还是Broadcom的,Google主要是做了和上层Framework相关的部分)。

 BluedroidBluez相比,有如下优点:

 

 ■ 层次结构清晰。各个profile对上层接口统一,便于增加新的profile

 ■ 增加了HAL层,便于移植。

 ■ 去掉了DBusFrameworkJava代码直接调用到BluedroidNative代码。

 

    但是Android 4.2中的BluedroidAndroid 4.0中的Bluez相比,功能要少,例如不支持AVRCP 1.3, Bug较多,例如某些蓝牙耳机不能重拨最后一个电话。最重要的是4.2Bluedroid不支持BLE。不过在刚刚发布的Android 4.3中已经有了很多改进,AVRCP 1.3BLE都得到了支持。

 

    目前有一些Android 4.14.2的设备是支持BLE的,但是都是采用的Vendor自己的解决方案,比如Bluetooth stack采用Bluez 5.x,再提供Vendor BLE Android SDK. 现在Android 4.4已经发布,从未来发展趋势来看,如果有人要学习Bluetooth in Android,建议不要再研究Bluez,最好转向Bluedroid

 

以下是Android 4.4 Bluetooth相关代码之分布:

 

android.bluetooth frameworks/base/core/java/android/bluetooth implements public API for the Bluetooth adapter and profiles

Bluetooth system service packages/apps/Bluetooth/src implements service and profiles at the Android fraework layer

Bluetooth JNI packages/apps/Bluetooth/jni defines Bluetooth adapter and profiles service JNI: calls into HAL and receives callback from HAL

Bluetooth HAL hardware/libhardware/include/hardware/bt_*.h files defines the standard interface that the android.bluetooth adapter and  profiles APIs

Bluetooth stack external/bluetooth/bluedroid implement bluetooth stack: core and profiles

 

    笔者在进行Bluetooth的调试过程中,使用Logcat 命令输出Android的调试信息,在AndroidSetting界面开启蓝牙功能,根据打印信息的输出,发现Enable Bluetooth的过程中出现了问题,最后查找原因是因为MT6620芯片工作前需要需要下载固件补丁,这个过程需要花费一定的时间,然后bluetooth.default.so 库文件代码中对开启Bluetooth有一定的时间限制,默认情况下是3000毫秒的超时时间,超时后会disable 蓝牙,后经笔者修改为20 000 毫秒,这样即可enable蓝牙芯片,从而进入工作状态.

 

修改文件:  iTop4412_KK4.4/external/bluetooth/bluedroid/Android.mk

 

 

 

 

 

 

 

1.5.2  init.connectivity.rc 文件

init.connectivity.rc 文件路径:

 

iTop4412_KK4.4/hardware/mediatek/config/combo_mt66xx/ init.combo_mt66xx.rc

 

原始文件名称为 init.combo_mt66xx.rc,拷贝到ramdiskroot目录下面名称变更为init.connectivity.rc文件 。

 

   我们在该文件增加了加载驱动模块库操作,运行wmt_lanucher服务操作,另外需要注意文件原有的创建bluetooth相关目录操作,及修改权限,变更拥有者,这些command非常的重要,比如:

 

# Load Blue module

    insmod /system/lib/modules/mtk_stp_bt.ko

 

 

    chmod 0660 /dev/stpbt

    chown bluetooth system /dev/stpbt

    mkdir /data/bluetooth 0711 bluetooth bluetooth

    mkdir /data/misc/bluedroid 0771 bluetooth bluetooth

 

1.5 总结

   用户在移植HAL层之前可以先使用MTK提供的蓝牙测试工具autobt进行测试,该测试工具脱落复杂的HAL层,直接调用libbt-vendor.so 也就是厂商自己的库文件,在Android的命令行中执行即可,可以使用该命令查询其他的蓝牙设备,发送,接收文件等等。是判断蓝牙硬件是否正常工作的有力工具,使用autobt测试通过后,再调试Android HAL及上层部分。

 

autobt工具的源码位于

 iTop4412_KK4.4/hardware/mediatek/utility/hw_test_tool/bluetooth/src/tool

 

另外MTK官方提供了Bluetooth的多个补丁,路径:

APEX_Android_4.4_MP_SW_package_V2.0/Document/BT_patch_description(must read)

 

   这些补丁是比较重要的,有关于蓝牙基础连接方面的,也有关于蓝牙文件发送接收,蓝牙鼠标,蓝牙耳机方面的,需要根据您的产品需求打对应的补丁,我们发布的Android4.4代码中已经打上了蓝牙基础连接,和文件发送接收方面的补丁,其他的补丁未处理.

      HAL层修改完成后在Android4.4Setting里面打开Bluetooth,就可以扫描到其他蓝牙设备,然后进行配对,配对完成后就可以进行文件的传输操作了,笔者仅测试了蓝牙的文件发送与接收功能,其他的蓝牙功能比如蓝牙耳机,蓝牙鼠标的使用均未进行测试,不过有了文件发送接收的测试基本说明了蓝牙的PortingOK的,如果您有兴趣或者需求,可以移植蓝牙其他更丰富的功能与应用。 

 

 

加载中
返回顶部
顶部