本專欄文章我們會以連載的方式持續更新,本專欄計劃更新內容如下:
第一篇:藍牙綜合介紹 ,主要介紹藍牙的一些概念,產生背景,發展軌跡,市面藍牙介紹,以及藍牙開發板介紹。
第二篇: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,
我們下面剩下的命令都不再貼了,大概用法應該都清楚了
整個的格式有點繞,我們來看下下圖可能你就一下清晰了!