最近在调试nxp的ap6256蓝牙模块驱动,写个笔记记录下心得。
一、设备树配置
设备树配置的东西就三点,节点配置。还有就是驱动要编译。
1)把驱动匹配进去
bt_rfkill: bt_rfkill {
compatible = "fsl,mxc_bt_rfkill";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_bt>;
bt-power-gpios = <&gpio4 24 GPIO_ACTIVE_HIGH>;
status ="okay";
};
驱动文件就大家自己去弄了
2)bt_rst的拉高
pinctrl_bt: wlangrp {
fsl,pins = <
MX8MP_IOMUXC_SAI2_TXFS__GPIO4_IO24 0x41 /* BT_RST */
MX8MP_IOMUXC_NAND_DATA00__GPIO3_IO06 0x16 /* BT_WAKE_HOST */
>;
};
3)对应的串口配置
蓝牙一般用串口通讯。
&uart3 {
/* BT */
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart3>;
fsl,uart-has-rtscts;
status = "okay";
};
pinctrl_uart3: uart3grp {
fsl,pins = <
MX8MP_IOMUXC_SD1_DATA6__UART3_DCE_TX 0x140
MX8MP_IOMUXC_SD1_DATA7__UART3_DCE_RX 0x140
MX8MP_IOMUXC_SD1_RESET_B__UART3_DCE_RTS 0x140
MX8MP_IOMUXC_SD1_STROBE__UART3_DCE_CTS 0x140
>;
};
同时需要去看有没有管角复用这些。
这样的话就可以在串口里面看到相关打印信息。
$> dmesg | grep -i Bluetooth
Bluetooth: Core ver 2.18
Bluetooth: HCI device and connection manager initialized
Bluetooth: HCI socket layer initialized
Bluetooth: L2CAP socket layer initialized
Bluetooth: SCO socket layer initialized
Bluetooth: HCI UART driver ver 2.2
Bluetooth: HCI H4 protocol initialized
Bluetooth: HCI BCSP protocol initialized
Bluetooth: HCIATH3K protocol initialized
Bluetooth: RFCOMM TTY layer initialized
Bluetooth: RFCOMM socket layer initialized
Bluetooth: RFCOMM ver 1.11
Bluetooth: BNEP (Ethernet Emulation) ver 1.3
Bluetooth: BNEP filters: protocol multicast
Bluetooth: BNEP socket layer initialized
Bluetooth: HIDP (Human Interface Emulation) ver 1.2
Bluetooth: HIDP socket layer initialized
如果是底层驱动,那么就可以用底层工具hci相关工具查看
$> hciconfig hci0 up
$> hciconfig
hci0: Type: BR/EDR Bus: UART
BD Address: 64:A3:CB:5B:69:F0 ACL MTU: 1021:8 SCO MTU: 64:1
UP RUNNING PSCAN
RX bytes:1772 acl:0 sco:0 events:69 errors:0
TX bytes:1152 acl:0 sco:0 commands:65 errors:0
如果这里面没有设备出来
$> hciconfig hci0 up
no device ***
这个就是关于蓝牙的固件没有加载进板子里面(我的这个是这样的,不敢说全部)。
二、固件加载
BCM4345C5.hcd
固件名字是这个
底层可以直接通过网口或者adb弄到板子上去,然后执行对应的命令就可以
安卓驱动需要指定对应的路径。
1)device/nxp/imx8m/evk_8mp/BoardConfig.mk
/*通过FILES把pc端文件传到板子上的指定目录*/
PRODUCT_COPY_FILES += \
device/nxp/imx8m/evk_8mp/firmware/bcm_ap6256/BT/BCM4345C5.hcd:vendor/etc/firmware/bcm/BCM4345C5.hcd
# -------@block_bluetooth-------
# AP6256 BT
2)可以在板子上查看是否有对应的固件,如果没有则不行,先把这个固件弄到板子上。如果有,那么可以先尝试去打开连接蓝牙。
查看对应的log,如果没问题,那么就ok。如果有问题则查看log寻找对应的问题。
12-24 02:32:48.128 2210 2211 I bt_vendor: init
12-24 02:32:48.128 2210 2211 I bt_vnd_conf: Attempt to load conf from /etc/bluetooth/bt_vendor.conf
12-24 02:32:48.128 2210 2211 I bt_vnd_conf: vnd_load_conf file >/etc/bluetooth/bt_vendor.conf< not found
12-24 02:32:48.129 2210 2211 E bt_upio : init_rfkill : open(/sys/class/rfkill/rfkill0/type) failed: No such file or directory (2)
12-24 02:32:48.129 2210 2211 W bt_vendor: NOTE: BT_VND_PWR_ON now forces power-off first
12-24 02:32:48.129 2210 2211 E bt_upio : init_rfkill : open(/sys/class/rfkill/rfkill0/type) failed: No such file or directory (2)
12-24 02:32:48.129 2210 2211 I bt_userial_vendor: userial vendor open: opening /dev/ttyO1
12-24 02:32:48.129 2210 2211 E bt_userial_vendor: userial vendor open: unable to open /dev/ttyO1
12-24 02:32:48.152 2164 2206 F libc : Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 2206 (bt_hci_thread), pid 2164 (droid.bluetooth)
12-24 02:32:48.207 2218 2218 I crash_dump64: obtaining output fd from tombstoned, type: kDebuggerdTombstone
我这里打印出了对应的log信息,发现蓝牙串口打开失败,或者打开错误。这里后面网上查看,自己寻找文件后发现这是因为没有指定打开那个串口,蓝牙厂商驱动将会尝试打开/dev/ttyO1所以会报错。
三、指定打开串口路径
在项目根目录下,有这样一个文件
hardware/broadcom/libbt/include/bt_vendor_brcm.h
打开后这里有对应的说明:
/* Run-time configuration file */
#ifndef VENDOR_LIB_CONF_FILE
#define VENDOR_LIB_CONF_FILE "/etc/bluetooth/bt_vendor.conf"
#endif
/* Device port name where Bluetooth controller attached */
#ifndef BLUETOOTH_UART_DEVICE_PORT
#define BLUETOOTH_UART_DEVICE_PORT "/dev/ttyO1" /* maguro */
#endif
/* Location of firmware patch files */
#ifndef FW_PATCHFILE_LOCATION
#define FW_PATCHFILE_LOCATION "/vendor/firmware/" /* maguro */
#endif
#ifndef UART_TARGET_BAUD_RATE
#define UART_TARGET_BAUD_RATE 3000000
#endif
所以我们需要给他指定对应的打开路径
这里有你对应的板子的编译文件和路径
vi hardware/broadcom/libbt/conf/nxp/evk_8mp/bt_vendor.conf
//打开后就可以设定路径
# UART device port where Bluetooth controller is attached
UartPort = /dev/ttymxc2
//修改固件路径
# Firmware patch file location
FwPatchFilePath = /vendor/etc/firmware/bcm
FwPatchFileName = BCM4345C5.hcd
如果没有这个文件,那么就是你需要在Android.mk文件里面去添加
hardware/broadcom/libbt/Android.mk
修改对应板级文件
ifeq ($(TARGET_PRODUCT), evk_8mp)
include $(LOCAL_PATH)/conf/nxp/evk_8mp/Android.mk
endif
hardware/broadcom/libbt/conf/nxp/evk_8mp/Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := bt_vendor.conf
LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc/bluetooth
LOCAL_SRC_FILES := $(LOCAL_MODULE)
include $(BUILD_PREBUILT)
然后再试试。
如果修改好了,那么串口应该有对应的打印消息
12-24 02:42:41.734 3194 3194 I bt_vendor: init
12-24 02:42:41.734 3194 3194 I bt_vnd_conf: Attempt to load conf from /vendor/etc/bluetooth/bt_vendor.conf
12-24 02:42:41.735 3194 3194 E bt_upio : init_rfkill : open(/sys/class/rfkill/rfkill0/type) failed: No such file or directory (2)
12-24 02:42:41.735 3194 3194 W bt_vendor: NOTE: BT_VND_PWR_ON now forces power-off first
12-24 02:42:41.735 3194 3194 E bt_upio : init_rfkill : open(/sys/class/rfkill/rfkill0/type) failed: No such file or directory (2)
12-24 02:42:41.735 3194 3194 I bt_userial_vendor: userial vendor open: opening /dev/ttymxc2
12-24 02:42:41.735 3194 3194 I bt_userial_vendor: device fd = 7 open
12-24 02:42:41.749 3194 3255 I bt_hwcfg: bt vendor lib: set UART baud 1000000
12-24 02:42:41.753 3194 3255 D bt_hwcfg: Chipset BCM4345C5
12-24 02:42:41.753 3194 3255 D bt_hwcfg: Target name = [BCM4345C5]
12-24 02:42:41.753 3194 3255 I bt_hwcfg: FW patchfile: /vendor/etc/firmware/bcm/BCM4345C5.hcd
12-24 02:42:42.206 3194 3255 I bt_hwcfg: bt vendor lib: set UART baud 115200
12-24 02:42:42.206 3194 3255 D bt_hwcfg: Settlement delay -- 100 ms
12-24 02:42:42.206 3194 3255 I bt_hwcfg: Setting fw settlement delay to 100
12-24 02:42:42.370 3194 3255 I bt_hwcfg: bt vendor lib: set UART baud 1000000
12-24 02:42:42.371 3194 3255 I bt_hwcfg: Setting local bd addr to 13:20:40:00:13:CB
12-24 02:42:42.371 3194 3255 I bt_hwcfg: vendor lib fwcfg completed
12-24 02:42:42.372 3210 3253 I bt_hci : event_finish_startup
12-24 02:42:42.373 3210 3235 I bt_core_module: module_start_up Started module "hci_module"
然后连接蓝牙,这里我们就可以打开蓝牙的,然后进行蓝牙连接配对。
手机和开发板好像只能配对,不能连接,如果要连接,需要修改蓝牙的配置。可以用蓝牙耳机连接。
四、BUG解决
从上面的log看
12-24 02:42:41.735 3194 3194 E bt_upio : init_rfkill : open(/sys/class/rfkill/rfkill0/type) failed: No such file or directory (2)
这里有一个bug,这个bug导致的问题在与,我们安卓通过上层的蓝牙开关去调用蓝牙的时候。第二次是无法打开的,显示的log如下
01-25 05:11:16.441 2309 2311 W bt_vendor: NOTE: BT_VND_PWR_ON now forces power-off first
01-25 05:11:16.441 2309 2311 E bt_upio : init_rfkill : open(/sys/class/rfkill/rfkill0/type) failed: No such file or directory (2)
01-25 05:11:16.441 2309 2311 I bt_userial_vendor: userial vendor open: opening /dev/ttymxc2
01-25 05:11:16.442 2309 2311 I bt_userial_vendor: device fd = 7 open
01-25 05:11:16.436 2309 2309 I HwBinder:2309_2: type=1400 audit(0.0:2884): avc: denied { read } for name="u:object_r:default_prop:s0" dev="tmpfs" ino=109 scontext=u:r:hal_bluetooth_default:s0 tcontext=u:object_r:default_prop:s0 tclass=file permissive=1
01-25 05:11:16.440 2309 2309 I HwBinder:2309_2: type=1400 audit(0.0:2886): avc: denied { getattr } for path="/dev/__properties__/u:object_r:default_prop:s0" dev="tmpfs" ino=109 scontext=u:r:hal_bluetooth_default:s0 tcontext=u:object_r:default_prop:s0 tclass=file permissive=1
01-25 05:11:19.337 2276 2303 E bt_hci : startup_timer_expired
01-25 05:11:19.337 2309 2311 I android.hardware.bluetooth@1.0-impl: BluetoothHci::close()
01-25 05:11:19.338 2309 2311 I bt_userial_vendor: device fd = 7 close
01-25 05:11:19.340 2309 2311 E bt_upio : init_rfkill : open(/sys/class/rfkill/rfkill0/type) failed: No such file or directory (2)
01-25 05:11:19.341 2309 2311 I android.hardware.bluetooth@1.0-impl: Firmware configured in 2.899s
01-25 05:11:19.341 2276 2303 F libc : Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 2303 (alarm_default_c), pid 2276 (droid.bluetooth)
01-25 05:11:19.438 2327 2327 F DEBUG : pid: 2276, tid: 2303, name: alarm_default_c >>> com.android.bluetooth <<<
01-25 05:11:19.502 2327 2327 F DEBUG : #01 pc 0000000000265434 /system/lib64/libbluetooth.so (startup_timer_expired(void*)+188) (BuildId: 3fae33ca1eda89f10865aeb654a96422)
01-25 05:11:19.502 2327 2327 F DEBUG : #02 pc 0000000000336e48 /system/lib64/libbluetooth.so (alarm_ready_generic(alarm_t*, std::__1::unique_lock<std::__1::mutex>&)+400) (BuildId: 3fae33ca1eda89f10865aeb654a96422)
01-25 05:11:19.503 2327 2327 F DEBUG : #03 pc 0000000000336c78 /system/lib64/libbluetooth.so (alarm_queue_ready(fixed_queue_t*, void*)+112) (BuildId: 3fae33ca1eda89f10865aeb654a96422)
01-25 05:11:19.503 2327 2327 F DEBUG : #04 pc 000000000033c090 /system/lib64/libbluetooth.so (internal_dequeue_ready(void*)+88) (BuildId: 3fae33ca1eda89f10865aeb654a96422)
01-25 05:11:19.503 2327 2327 F DEBUG : #05 pc 000000000033d714 /system/lib64/libbluetooth.so (run_reactor(reactor_t*, int)+388) (BuildId: 3fae33ca1eda89f10865aeb654a96422)
01-25 05:11:19.503 2327 2327 F DEBUG : #06 pc 000000000033d560 /system/lib64/libbluetooth.so (reactor_start(reactor_t*)+88) (BuildId: 3fae33ca1eda89f10865aeb654a96422)
01-25 05:11:19.503 2327 2327 F DEBUG : #07 pc 000000000033f088 /system/lib64/libbluetooth.so (run_thread(void*)+184) (BuildId: 3fae33ca1eda89f10865aeb654a96422)
01-25 05:11:19.528 221 221 I hwservicemanager: getTransport: Cannot find entry android.hardware.bluetooth@1.1::IBluetoothHci/default in either framework or device manifest.
01-25 05:11:19.529 2330 2330 E HidlServiceManagement: Service android.hardware.bluetooth@1.1::IBluetoothHci/default must be in VINTF manifest in order to register/get.
这里导致的原因猜测在于没有对应的节点,去控制蓝牙的上下电,当你上层关闭蓝牙的时候,其实蓝牙内部的还在工作,当你再次打开蓝牙的时候,他没有去初始化关电,导致的你的蓝牙无法打开。所以要把节点配置出来,通过节点去控制蓝牙的上下电。
这里需要修改你对应的defconfig文件
kernel_imx/arc/arm64/xxxdefconig
在里面添加对应的rfkill节点
CONFIG_RFKILL=y
CONFIG_RFKILL_INPUT=y
CONFIG_RFKILL_GPIO=y
#CONFIG_BT_HCIVHCI=y
#CONFIG_BT_HCIUART=y
#CONFIG_BT_HCIBFUSB=y
#CONFIG_BT_HCIBTSDIO=y
#CONFIG_BT_HCIRFKILL=y
#CONFIG_DEBUG_FS=y
下面那几个好像是配置蓝牙的功能的,这个bug对应的上面三个节点就可以,完成后可以在你的镜像文件目录下查看.config文件里面有没有对应的编译
/out/target/product/evk_8mp/obj/KERNEL_OBJ
vi .config
CONFIG_RFKILL_LEDS=y
CONFIG_RFKILL_INPUT=y
CONFIG_RFKILL_GPIO=y
可以看到对应的东西已经生成,再进入板子里面
2|evk_8mp:/ # ls sys/class/rfkill/rfkill0/state
sys/class/rfkill/rfkill0/state
也有对应的节点生成
可能还有一个问题就是你没有权限去读写,可能也会导致上面的bug
evk_8mp:/ # ls -l sys/class/rfkill/rfkill0/state
-rw-rw-rw- 1 root root 4096 2022-01-28 07:46 sys/class/rfkill/rfkill0/state
修改点在/system/core/rootdir/init.rc
添加下面一行代码
chmod 0666 /sys/class/rfkill/rfkill0/state
到此蓝牙可以连续的开和关,没有其余的bug。