接第二篇,start_up
到最后都是要以文件以目录为思考,不用跳来跳去找
先是hci_layer.c
这里直接就进来vendor了,我们先分析一下结构
vendor_t不是最终的接口,要找一下,通过vendor_get_interface去拿,在哪里
接口是在这里的,
所以hci_layer.c调用的是 vendor.c的vendor_open
看看vendor_open
vendor.c 调用vendor_open打开 libbt-vendor_usb.so或者是libbt-vendor_uart.so或者是libbt-vendor.so
#ifdef BLUETOOTH_RTK
#include "bdroid_buildcfg.h"
static const char *VENDOR_LIBRARY_NAME_USB = "libbt-vendor_usb.so";
static const char *VENDOR_LIBRARY_NAME_UART = "libbt-vendor_uart.so";
#endif
static const char *VENDOR_LIBRARY_NAME = "libbt-vendor.so";
libbt-vendor_usb.so和libbt-vendor_uart.so 是realtek原厂的vendor
libbt-vendor.so 是博通的,比较常用的就是这两个
lib_interface = (bt_vendor_interface_t *)dlsym(lib_handle, VENDOR_LIBRARY_SYMBOL_NAME);
这个时候我们拿到vendor的interface
lib_interface->init(&lib_callbacks, (unsigned char *)local_bdaddr);
然后进行初始化,
这个时候从vendor.c就要跑到 vendor.so上去了,以博通的vendor来说一下,都差不多的
lib_interface->init(&lib_callbacks, (unsigned char *)local_bdaddr);
这个init的函数跑的是bt_vendor_brcm.c
bt_vendor_brcm.c中的init就是vendor.so的init函数,vendor有两个接口,
1、bt_vendor_interface_t (这个接口比较简单)
2、bt_vendor_callbacks_t (这个接口比较难,执行部分多在这里)
bt_vendor_callbacks_t 由上层实体化,底层调用时,由上层传下来,这里不简单,
好比在底层
a.c中
b()
a()
{
b();
}
在a中运行本模块的b,理论上直接调用就像上面那样,但是它不可以,因为不只是简单的运行b(),比如我们需要用thread来管理它,对对对,要丢给bluedroid的协议栈中hci去管理这个b的运行
就要变成如下
b()
a()
{
hci->manage(b());
}
所以才有了callbak,真正的管理函数在上层,底层就需要把上层的实体拿过来使用。
那么究竟是要跑哪些函数呢
主要在hardware.c,最经典就是hw_config_cback函数,这里就是蓝牙打开串口,发reset指令,发读local name指令
发下载patch指令的初始化过程
hw_config_cback这个函数,在我的印象中,不管是单片机rtos,还是linux,或者是andorid,运行起来都是一样的方法,可能名字不一样
就像一个炸弹一样,运行一下就会嘣嘣嘣嘣嘣
就像成语接龙一样,接力式运行
怎么运行的看看
首先运行到1,第一次设置串口为115200(rtk是这样,两次设置不同的波特率)
这种成语接龙的函数就是靠switch来实现的
运行了1,就会跳到2,
方法是运行到1的后面,将state修改
hw_cfg_cb.state = HW_CFG_READ_LOCAL_NAME;
然后再开一个hw_config_cback函数,当前的hw_config_cback break掉
新开一个方法就是刚刚说的回调,让上层去管理,再开一个hw_config_cback
bt_vendor_cbacks->xmit_cb(HCI_READ_LOCAL_NAME, p_buf, hw_config_cback);
switch(a)
{
1:
state =2;
break;
2:
state =3;
break;
3:
state =4 ;
break;
}
所以只要运行了1,就会成语接龙停不下来,直接就是1->2-3->4,直到最后
在rtos的实现比较简单,直接套用while(1)
while(1)
{
switch();
}
然后在定时器那边去修改state,直到跑完,主要是要拿controller的event,才有这种逻辑。
总之hw_config_cback这个函数外部调用一次就可以初始化了,或者里面没有state的,也可以拿来调用,比如读一下mac地址
rtk主要是
set baud(115200)->sync -> config->read local name ->set baud and flow control(1.5M)-> download patch->reset
broadcom主要是
set baud(1.5M)->reset ->read local name-> set baud(1.5M) ->download patch ->reset
broadcom是模组是默认打开流控的而且都是uart的(rtk有usb的接口),而且没有修改,就是直接打开的,UART RTS必须有一个脉冲,RTS和CTS接地本来是去掉流控最好的方法,但是呢,博通的IC有检查RTS是否OK的动作,所以,这样是不行的,
RTK的可以,而且RTK的流控只需接3根线就可以了,BT RX BT TX BT CTS
BT RTS不用接,HOST CTS直接接地,意思就是说,我模组永远都不用忙等待,你可以直接发过来
如果HOST端的RTS IOMUX异常就是被复用的话,BT CTS一直为高,导致模组一直没有数据发出来,所以要注意流控,
特别是模组本身,是否打开流控,自己主控才好控制。
控制host的流控主要是在userial_vendor.c,控制control的设置主要是发命令在bt_vendor_brcm.c
vendor 文件很少的,主要就是打开串口,然后拿到串口去发数据,接数据
最后再说一下H4 和H5的问题,主要是H4没有重传,H5有重传,抗干扰能力强
BLUETOOTH_RTK宏在
H4和H5不是你说想要就想要的,必须要先确认模组是H4还是H5,realtek是可以改efuse的,修改H5或者H4,正常自带都是H5
因为你生产不可能一个个去改efuse,所以从拿货的时候就要先确定好
博通的话只有H4
说了半天,完全没有看到正在打开蓝牙,打开,就是上电啊,在哪里上电啊,放到第四篇说