本专栏文章我们会以连载的方式持续更新,本专栏计划更新内容如下:
第一篇:蓝牙综合介绍 ,主要介绍蓝牙的一些概念,产生背景,发展轨迹,市面蓝牙介绍,以及蓝牙开发板介绍。
第二篇:Transport层介绍,主要介绍蓝牙协议栈跟蓝牙芯片之前的硬件传输协议,比如基于UART的H4,H5,BCSP,基于USB的H2等
第三篇:传统蓝牙controller介绍,主要介绍传统蓝牙芯片的介绍,包括射频层(RF),基带层(baseband),链路管理层(LMP)等
第四篇:传统蓝牙host介绍,主要介绍传统蓝牙的协议栈,比如HCI,L2CAP,SDP,RFCOMM,HFP,SPP,HID,AVDTP,AVCTP,A2DP,AVRCP,OBEX,PBAP,MAP等等一系列的协议吧。
第五篇:低功耗蓝牙controller介绍,主要介绍低功耗蓝牙芯片,包括物理层(PHY),链路层(LL)
第六篇:低功耗蓝牙host介绍,低功耗蓝牙协议栈的介绍,包括HCI,L2CAP,ATT,GATT,SM等
第七篇:蓝牙芯片介绍,主要介绍一些蓝牙芯片的初始化流程,基于HCI vendor command的扩展
第八篇:附录,主要介绍以上常用名词的介绍以及一些特殊流程的介绍等。
另外,开发板如下所示,对于想学习蓝牙协议栈的最好人手一套。以便更好的学习蓝牙协议栈,相信我,学完这一套视频你将拥有修改任何协议栈的能力(比如Linux下的bluez,Android下的bluedroid)。
------------------------------------------------------------------------------------------------------------------------------------------
CSDN学院链接(进入选择你想要学习的课程):https://edu.csdn.net/lecturer/5352?spm=1002.2001.3001.4144
蓝牙交流扣扣群:970324688
Github代码:https://github.com/sj15712795029/bluetooth_stack
入手开发板:https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w4004-22329603896.18.5aeb41f973iStr&id=622836061708
------------------------------------------------------------------------------------------------------------------------------------------
众所周知,由于SIG规定的一些HCI command跟event不能完全满足各个芯片原厂的需求,所以芯片原厂会在SIG规定的基础上去扩展一些command & event,这个就叫做hci vendor & command,这个SIG已经把vendor command的OGF跟event code已经定义好!hci vendor command的OGF是0x3F,我们来看下core spce的原话,
其中hci vendor command的格式还是会依照hci command的格式来,只不过para部分就是芯片厂商自定义的格式了,也就是红框部分是芯片厂商自己定义
而controller回复host的event有可能是0x0e,也就是command complete,也有可能是0xff ,也就是vendor event code,这个根据芯片不同而不同,这个跟hci command是一个到底,还是会根据hci event的格式来,只不过payload是芯片厂商自定义
包括其中几个filed(参照文档:HCI Externsions(bcore-an-009Pb.pdf))
① 前两个byte是HCI command的opcode,也就是OGG为0x3f(vendor command),OCF为0,如图:
② para len:参数的长度:也就是后面参数的长度,不包括opcode以及para len
③ parameter:参数部分,从次部分就是csr自己定义的格式,下个小节我们来做说明
此小节我们主要来说明下红框部分,也就是HCI command的param部分
其中csr vendor 部分一共分为几个field
① Payload Descriptor部分
上面说明已经很明白,也就是我们如果只有一包完整的数据,那么first跟last都要设置为1
Channel ID有以下值:
由于我们大部分时间还是只用到BCCMD,所以我们只要给予BCCMD来说明,后续如果会用到HQ等其他channel,BCCMD的话我们的channel是2,整个我们Payload Descriptor的值为11000010b,也就0xc2,
② Payload部分
也就是是红框部分
整个payload格式为:
注意,这里的单位的是uint16s,也就是header是10byte,
下面我们就一一来说明下整个格式:
Type: 标示消息类型,一共有以下几种值:
Length:数据长度,包括Type跟Length部分,注意他的长度是以16bit为单位,也就是2个byte,这里要写1
Seqno: 数据包序号
Varid: 消息id,后续我们再csr8311初始化的时候会用到两种类型,一种是PS,一种是warm reset,后续我们再介绍
Status:状态,一共有以下值:
Payload: 特定的消息id,附带的信息,这个我们在初始化的时候会详细介绍
vendor event也是遵循了hci event的格式,其中0xff就是vendor event的id,其中红框部分就是整个vendor event的格式
所有的field我们在command中已经介绍,我们就不再重复
我们就随便拿个例子举例,这样能加深格式印象
我们就拿这个举例吧:
其中command的整个数据为(Hex):00 FC 13 C2 02 00 09 00 02 00 03 70 00 00 29 02 01 00 08 00 00 00
其中event的整个数据为(Hex):FF 13 C2 01 00 09 00 02 00 03 70 00 00 29 02 01 00 08 00 00 00
我们先来分析下command:
00 FC -》HCI vendor command opcode
13 -》HCI comamnd para len,也就是19byte
C2 -》Payload Descriptor, 也就是表示fist&last pack,并且channel id是2,也就是bccmd
02 00 -》Type为2,也就是SETREQ
09 00 -》 长度,也就是在Payload Descriptor之后的长度
02 00 -》SeqNo
03 70 -》Varid,这里其实就是BCCMD的PS知名,后续再介绍
00 00 -》Status,OK
29 02 01 00 08 00 00 00 -》PS指令的格式,后续再介绍
然后我们再分析下event:
FF -》HCI vendor event code
13 -》 HCI event param len,也就是19byte
C2 -》Payload Descriptor, 也就是表示fist&last pack,并且channel id是2,也就是bccmd
01 00 -》 Type为1,也就是GETRESP
09 00 -》 长度,也就是在Payload Descriptor之后的长度
02 00 -》SeqNo
03 70 -》Varid,这里其实就是BCCMD的PS知名,后续再介绍
00 00 -》Status,OK
29 02 01 00 08 00 00 00 -》PS指令的格式,后续再介绍
PS指令就是把一些值写到芯片的特定位置中(RAM,ROM,FLASH,EEPROM),让其根据我们写的值来工作
整个框架如下图:
还记得这张图BCCMD的图吗?忘记了没关系我们再贴下
其中Varid就是命令ID,我们PS是值是0x7003,其中payload,我们一般叫做pskey,这回你终于知道整个CSR的名词的关联性了吧,整个格式如下:
对应关系我们再贴下,方便加深下印象!
其中header部分我们已经在前面小节介绍过,接下来我们来说明下PS的格式:
Key:就是pskey文档中的key number,CSR(现高通)文章中有几百个key number,但是不要慌,我们能修改的很少,一般vendor厂商会针对不同芯片给pskey,但是我们也要把常用的了解下,方便针对我们的需求修改,例子我们最终再举例初始化的时候说明下
Length:只是PS value的长度
Stores:标示存储的地方,这里要区分是SETREQ还是GETREQ
SETREQ可以访问的值有:
GETREQ可以访问的值有:
可能你会对于你会对psi,psf等这些名词比较懵,别急,上图:
可以看到CSR8311在初始化的时候下了这么多vendor command
整个command为:
// Set PSKEY_DEEP_SLEEP_STATE never deep sleep
0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x02, 0x00, 0x03, 0x70, 0x00, 0x00, 0x29, 0x02, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00,
// Set ANA_Freq to 26MHz
0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x03, 0x00, 0x03, 0x70, 0x00, 0x00, 0xfe, 0x01, 0x01, 0x00, 0x08, 0x00, 0x90, 0x65,
// Set CSR_PSKEY_ANA_FTRIM 0x24 for csr8811
0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x04, 0x00, 0x03, 0x70, 0x00, 0x00, 0xf6, 0x01, 0x01, 0x00, 0x08, 0x00, 0x24, 0x00,
// Set CSR_PSKEY_DEFAULT_TRANSMIT_POWER 0x4
0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x05, 0x00, 0x03, 0x70, 0x00, 0x00, 0x21, 0x00, 0x01, 0x00, 0x08, 0x00, 0x04, 0x00,
// Set CSR_PSKEY_MAXIMUM_TRANSMIT_POWER 0x4
0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x06, 0x00, 0x03, 0x70, 0x00, 0x00, 0x17, 0x00, 0x01, 0x00, 0x08, 0x00, 0x04, 0x00,
// Set CSR_PSKEY_BLE_DEFAULT_TRANSMIT_POWER 0x4
0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x07, 0x00, 0x03, 0x70, 0x00, 0x00, 0xc8, 0x22, 0x01, 0x00, 0x08, 0x00, 0x04, 0x00,
// Set CSR_PSKEY_BDADDR
0x19, 0xc2, 0x02, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x03, 0x70, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x08, 0x00, 0x20, 0x00, 0x98, 0x1a, 0x86, 0x00, 0x1d, 0x00,
// Set CSR_PSKEY_PCM_CONFIG32
0x15, 0xc2, 0x02, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x03, 0x70, 0x00, 0x00, 0xb3, 0x01, 0x02, 0x00, 0x08, 0x00, 0x80, 0x08, 0x80, 0x18,
// Set CSR_PSKEY_PCM_FORMAT 0x60
0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x03, 0x70, 0x00, 0x00, 0xb6, 0x01, 0x01, 0x00, 0x08, 0x00, 0x60, 0x00,
// Set CSR_PSKEY_USER_LOW_JITTER_MODE
0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x0b, 0x00, 0x03, 0x70, 0x00, 0x00, 0xc9, 0x23, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00,
// Set HCI_NOP_DISABLE
0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x0c, 0x00, 0x03, 0x70, 0x00, 0x00, 0xf2, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00,
// Set UART baudrate to 921600
0x15, 0xc2, 0x02, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x03, 0x70, 0x00, 0x00, 0xea, 0x01, 0x02, 0x00, 0x08, 0x00,0x0e,0x00,0x00,0x10,/*0x1b, 0x00, 0x40, 0x77,*/
// WarmReset
0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x0e, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
整个每行是一个命令,其中第一个byte是没有最终下到controller中的,只是为了解析方便加一个长度而已,下面我们就从第一条开始说明下(BCCMD格式我们已经在前面介绍,所以重点不是在解析bccmd,这里说明的重点是pskey):
① Set PSKEY_DEEP_SLEEP_STATE never deep sleep
0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x02, 0x00, 0x03, 0x70, 0x00, 0x00, 0x29, 0x02, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00,
可以看到这个是BCCMD PS命令(varid是0x7003),pskey的值为红色部分
0x29, 0x02, -> 0x229 pskey
0x01, 0x00, -> len,也就是value是1,也就是2个byte
0x08, 0x00, -> stores,也就是存储在psram中
0x00, 0x00, -> ps value值
下面我们来看下0x229的作用
② Set ANA_Freq to 26MHz
0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x03, 0x00, 0x03, 0x70, 0x00, 0x00, 0xfe, 0x01, 0x01, 0x00, 0x08, 0x00, 0x90, 0x65,
可以看到这个是BCCMD PS命令(varid是0x7003),pskey的值为红色部分
0xfe, 0x01, -> 0x1fe pskey
0x01, 0x00, -> len,也就是value是1,也就是2个byte
0x08, 0x00, -> stores,也就是存储在psram中
0x90, 0x65, -> ps value值
下面我们来看下0x01fe的作用
③ Set CSR_PSKEY_ANA_FTRIM 0x24 for csr8811
0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x04, 0x00, 0x03, 0x70, 0x00, 0x00, 0xf6, 0x01, 0x01, 0x00, 0x08, 0x00, 0x24, 0x00,
④ Set CSR_PSKEY_DEFAULT_TRANSMIT_POWER 0x4
0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x05, 0x00, 0x03, 0x70, 0x00, 0x00, 0x21, 0x00, 0x01, 0x00, 0x08, 0x00, 0x04, 0x00,
⑤ Set CSR_PSKEY_MAXIMUM_TRANSMIT_POWER 0x4
0x13, 0xc2, 0x02, 0x00, 0x09, 0x00, 0x06, 0x00, 0x03, 0x70, 0x00, 0x00, 0x17, 0x00, 0x01, 0x00, 0x08, 0x00, 0x04, 0x00,
我们下面剩下的命令都不再贴了,大概用法应该都清楚了
整个的格式有点绕,我们来看下下图可能你就一下清晰了!