1、前言
今年3月份调度了RK3568驱动程序,当时由于时间的问题,AP6275S蓝牙驱动程序没有调试成功。当时仔细检查的设备树的配置。
wireless_bluetooth: wireless-bluetooth {
compatible = "bluetooth-platdata";
clocks = <&rk809 1>;
clock-names = "ext_clock";
//wifi-bt-power-toggle;
uart_rts_gpios = <&gpio2 RK_PB1 GPIO_ACTIVE_LOW>;
pinctrl-names = "default", "rts_gpio";
pinctrl-0 = <&uart8m0_rtsn>;
pinctrl-1 = <&uart8_gpios>;
BT,reset_gpio = <&gpio4 RK_PB7 GPIO_ACTIVE_HIGH>;
BT,wake_gpio = <&gpio4 RK_PB6 GPIO_ACTIVE_HIGH>;
BT,wake_host_irq = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>;
status = "okay";
};
AP6275S使用外部时钟,RK3568程序工作后,hciconfig查看不到蓝牙设备。检测dmesg启动的流程关于bluetooth部分也没有发现问题:
firefly@firefly:~$
firefly@firefly:~$ dmesg | grep BT
[ 1.649733] [BT_RFKILL]: Enter rfkill_rk_init
[ 1.651127] [BT_RFKILL]: bluetooth_platdata_parse_dt: get property: uart_rts_gpios = 73.
[ 1.651169] [BT_RFKILL]: bluetooth_platdata_parse_dt: get property: BT,reset_gpio = 143.
[ 1.651186] [BT_RFKILL]: bluetooth_platdata_parse_dt: get property: BT,wake_gpio = 142.
[ 1.651202] [BT_RFKILL]: bluetooth_platdata_parse_dt: get property: BT,wake_host_irq = 135.
[ 1.651273] [BT_RFKILL]: Request irq for bt wakeup host
[ 1.651367] [BT_RFKILL]: ** disable irq
[ 1.651500] [BT_RFKILL]: bt_default device registered.
[ 7.877390] [BT_RFKILL]: rfkill_rk_set_power: set bt wake_host high!
[ 7.930246] [BT_RFKILL]: ENABLE UART_RTS
[ 8.036706] [BT_RFKILL]: DISABLE UART_RTS
[ 8.036757] [BT_RFKILL]: bt turn on power
[ 8.036787] [BT_RFKILL]: Request irq for bt wakeup host
[ 8.036829] [BT_RFKILL]: ** disable irq
firefly@firefly:~$
后来,又对比一个硬件的原理图与开发板的原理图,发现AP6275S的蓝牙串口的RTS,CTS未连接,因此修改硬件飞线连接,蓝牙还是没有设备出来。
2、转机
在蓝牙未调试出来后的这段时间,一直忙于项目管理上的杂事(未写代码),平时小憩时候一直在想这个问,为什么蓝牙不通,蓝牙使用串口来进行通信,串口在设备树中又没有配置,查看蓝牙驱动程序也没有串口相关的操作,只有串口RTS, CTS的电平控制。这个疑问一直萦绕在脑海中,为什么呢?
直到写文章的上一周,看到了篇文章,给解决问题找到的了新的思路:AP6275S移植总结
里面有一个brcm_patchram_plus -d --enable_hci --no2bytes --tosleep 200000 --baudrate 1500000 --patchram /system/etc/firmware/BCM4362A2.hcd /dev/ttyS4 &这个指令用于给蓝牙模块下载程序的命令。我马上在我这台设备试了一下,发现设备没有brcm_patchram_plus命令,而有brcm_patchram_plus1命令,那就用brcm_patchram_plus1来测试,实际连接的是串口8,所以修改命令执行一次,蓝牙设备出来了。看来问题的原因就是未执行这条指令导出。
马上查看了开发的文件系统,ps -ef | grep brcm,查看到有这个线程在工作。
firefly@firefly:~$ ps -ef | grep brcm
root 673 1 0 17:44 ? 00:00:00 /usr/bin/brcm_patchram_plus1 --enable_hci --no2bytes --use_baudrate_for_download --tosleep 200000 --baudrate 1500000 --patchram /system/etc/firmware/BCM4362A2.hcd /dev/ttyS8
firefly 1506 1329 0 18:25 pts/0 00:00:00 grep --color=auto brcm
firefly@firefly:~$
3、开机自启动蓝牙
在找到问题后,就要解决为什么我自己做的板子的系统开机不能自动执行蓝牙固件下载的功能?
通过一边学习系统启动相关知识,一边动手调试,得出可以通过以下几条命令先后找到这个线程启动的位置。brcm_patchram_plus1程序是由init进程启动,那在哪里启动的呢?
通pstree -a命令获取到进程树:systemd程序启动的这个brcm_patchram_plus
看来找systemd程序,这是一个系统服务相关的程序,使用systemctl status。查到有一个bt-attach.service服务启动的。
找到bt-attach.service这个服务的位置 /etc/systemd/system$下面
查看服务内容,得出启动的程序是/usr/bin/bt-attach。问题应该是出在这里。
firefly@firefly:/usr/bin$ cat bt-attach
#!/usr/bin/env bash
model_name=$(tr -d '\0' </sys/firmware/devicetree/base/model | tr 'a-z' 'A-Z')
while read line
do
chip_name=$(echo ${line} | cut -d ' ' -f 1)
if [[ ${model_name} == *3588* ]]; then
uart=$(basename /sys/firmware/devicetree/base/pinctrl/wireless-bluetooth/uart*-gpios | tr -cd "[0-9]")
uart="/dev/ttyS${uart}"
break
elif [[ ${model_name} == *${chip_name}* ]]; then
uart=$(echo ${line} | cut -d ' ' -f 2)
break
fi
done < /usr/bin/bt_uart.cfg
bt_type=$(rk_wifi_gettype)
rtk_attach() {
ret=`ps -ef |grep rtk_hciattach |grep -v "grep" |wc -l`
if [ ${ret} = 1 ]; then
killall rtk_hciattach
sleep 1
fi
/usr/bin/rtk_hciattach -n -s 115200 ${uart} rtk_h5 1500000 noflow &
}
if [[ ${bt_type} = "RTL"* ]]; then
rtk_attach
exit 0
else
killall brcm_patchram_plus1
#uart="/dev/ttyS8"
fwname=$(/usr/bin/bt_fwname ${uart})
echo "zsm $fwname"
if [[ ${fwname} = "bcm43438a1.hcd" ]]; then
ln -sf /vendor/etc/firmware/nvram_ap6212a.txt /vendor/etc/firmware/nvram.txt
elif [[ ${fwname} = "BCM4345C0.hcd" ]]; then
ln -sf /vendor/etc/firmware/nvram_ap6255.txt /vendor/etc/firmware/nvram.txt
fi
start-stop-daemon --start --oknodo --pidfile /var/run/hciattach.pid --background --startas \
/usr/bin/brcm_patchram_plus1 -- --enable_hci --no2bytes --use_baudrate_for_download \
--tosleep 200000 --baudrate 1500000 --patchram /system/etc/firmware/${fwname} ${uart}
fi
exit 0
仔细的分析一下这个脚本,它会读取/sys/firmware/devicetree/base/model这个文件,这个文件的内容来自于设备树中。脚本从这里来读取CPU的型号,之后再从bt_uart.cfg中读取蓝牙的串口号配置。问题出在我修改了设备树中model,没有写cpu型号,加上cpu型号RK3568后,这个脚本程序可以正常读取取串口号,启动蓝牙模块 AP6275S了。