打印
[CC2640]

CC2640R2F BLE5.0 蓝牙协议栈Host控制接口(HCI)

[复制链接]
825|12
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
coshi|  楼主 | 2020-2-2 11:55 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
Host控制接口(HCI)
主控制器接口(HCI)层是在蓝牙协议栈的主机(Host)和控制器(controller)之间传送命令和事件的薄层。在纯网络处理器应用程序(即host_test项目)中,HCI层通过SPI或UART等传输协议实现。

在诸如simple_peripheral项目的嵌入式无线MCU项目中,HCI层通过无线MCU内的函数调用和回调来实现。所有与Controller进行通信的命令和事件(如ATT,GAP等)将最终称为HCI API,从协议栈的Host通过HCI层传递到Controller。同样,控制器通过HCI将接收到的数据和事件发送到Host上层。

除了标准的蓝牙LE HCI命令之外,还有许多HCI扩展供应商特定的命令可以扩展控制器的一些功能,以供应用使用。有关在嵌入式应用程序中调用的可用HCI和HCI扩展命令的描述,请参阅BLE Stack API参考。

BLE5-Stack支持纯网络处理器配置(host_test),即允许应用程序在外部MCU上运行以连接到BLE5-Stack。网络处理器可以通过外部传输协议(UART,SPI等)接受所有LE HCI命令; 然而,因为 BLE Controller和Host都驻留在无线MCU上,所以一些HCI命令将使其相应的事件被TI BLE主机消耗。因此,不可能使用标准HCI LE命令将外部的蓝牙主机与CC2640无线MCU进行接口连接。网络处理器配置应使用HCI和TI供应商特定的HCI命令来实现外部蓝牙应用。

类似于网络处理器配置(host_test),BLE5-Stack可以被配置为使用子集HCI命令,然后通过UASRT,SPI传递给控制器​​,从而能够切换到完整的嵌入式应用。此配置称为生产测试模式(PTM)。可用的HCI命令的子集是执行蓝牙RF认证的子集。有关如何在嵌入式应用程序上启用PTM的信息,请参阅使用生产测试模式(PTM)。

当需要满足以下条件时,应考虑将PTM用于直接测试模式(DTM),以代替完整的网络处理器配置(host_test):

设备只会烧写一次FLASH在生产过程中。并且固件镜像无法再更改

HCI传输层FLASH可用,PTM需要FLASH在应用程序,因此减少应用程序FLASH

注意
BLE5-Stack也支持直接测试模式(DTM)。DTM在蓝牙核心规范版本5.0的直接测试模式部分([第6卷,第F部分))中有详细描述。Host_test支持所有DTM命令以及供应商特定的调制解调器测试命令。有关如何设置用于定制产品和芯片包类型的host_test应用程序二进制文件的信息,请参阅配置CC2640的蓝牙直接测试模式(SWRA530)。


使用特权

评论回复

相关帖子

沙发
coshi|  楼主 | 2020-2-2 11:56 | 只看该作者
在应用程序中使用HCI和HCI供应商特定的命令
按照以下步骤使用这些命令并在应用程序中接收各自的事件:

1.包括HCI传输层头文件。
        `#include  “hci_tl.h”`
2.注册用于HCI/Host消息的GAP,以便从控制器接收事件。这应该在应用程序初始化函数中完成。
        //注册GAP用于HCI /主机消息
        GAP_RegisterForMsgs (selfEntity );
3.应用程序能调用HCI或HCI特定于供应商的命令。请参阅BLE Stack API Reference,HCI部分具体介绍可以发送哪些命令。

4.作为HCI_GAP_EVENT_EVENT的任务间消息返回HCI事件 。请参阅simple_peripheral项目。





使用特权

评论回复
板凳
coshi|  楼主 | 2020-2-2 11:57 | 只看该作者
以下部分讨论接收HCI事件和HCI供应商特定的事件。

标准LE HCI命令和事件
这些命令在“ 蓝牙核心规范版本5.0”的“HCI命令和事件”一章(第2卷,第E部分,第7节)中有记录。使用这些命令的机制与蓝牙核心规范版本5.0中的任何命令相同,包括HCI LE命令。下面的示例演示了如何使用 蓝牙核心规范版本5.0在应用程序中实现HCI命令。使用的命令是读RSSI命令。

发送HCI命令
1.在蓝牙核心规范版本5.0中查找命令:


2.查找映射到BLE堆栈命令。使用BLE Stack API参考(HCI部分 -> HCI功能映射),显示此命令映射到HCI_ReadRssiCmd()。

3.使用步骤1中的API,填写参数并从应用程序的某处调用命令。在形成连接后,应该调用此特定命令。这里只有一个参数:一个2字节的连接句柄。在这个例子的情况下,连接句柄是0x0000:

        `HCI_ReadRssiCmd (0x0000);`


使用特权

评论回复
地板
coshi|  楼主 | 2020-2-2 11:57 | 只看该作者
接收HCI event

注意:确保注册消息;否则事件不会发送到应用程序,使用GAP_RegisterForMsgs()注册GAP消息

1.查看蓝牙核心规范版本5.0以查看返回事件的格式:


使用特权

评论回复
5
coshi|  楼主 | 2020-2-2 11:58 | 只看该作者
2.此命令返回一个Command complete事件(hciEvt_CmdComplete_t),因此在处理HCI_GAP_EVENT_EVENT时将其添加。这在下面进一步详细说明。                static  uint8_t  SimpleBLEPeripheral_processStackMsg (ICall_Hdr *  pMsg )
                {
                   uint8_t  safeToDealloc  =  TRUE ;
                   switch  (pMsg - > event )
                   {
                      case  HCI_GAP_EVENT_EVENT :
                      {
                         //处理HCI消息切换(pMsg-> status)
                      {
               
                      //处理HCI命令完成事件情况
                      HCI_COMMAND_COMPLETE_EVENT_CODE :
                      {
                         //解析命令完成事件的操作码和状态
                         hciEvt_CmdComplete_t *  command_complete  =  (hciEvt_CmdComplete_t * ) pMsg ;
                         uint8_t  status  =  command_complete - > pReturnParam [ 0 ];
               
                         // find which command complete is for
                         switch  (command_complete - > cmdOpcode )
                         {
                            case  HCI_READ_RSSI :
                            {
                               if  (status  ==  SUCCESS )
                               {
                                  uint16_t  handle  =  BUILD_UINT16 ( command_complete - > pReturnParam [ 2 ], command_complete - > pReturnParam [ 1 ] );
               
                                  //检查句柄
                                  if  (handle  ==  0x00 )
                                  {
                                     //存储RSSI
                                     uint8_t  rssi  =  command_complete - > pReturnParam [ 3 ];



首先,检查堆栈消息的状态以查看它是什么类型的HCI事件。在这种情况下,它是一个 HCI_COMMAND_COMPLETE_EVENT_CODE。然后,将作为消息(pMsg)从堆栈返回的事件转换为hciEvt_CmdComplete_t,其定义为:

        // Command Complete Event typedef struct
        {
          osal_event_hdr_t  hdr ;
          uint8  numHciCmdPkt ;
          uint16  cmdOpcode ;
          uint8 *  pReturnParam ;
        }  hciEvt_CmdComplete_t ;
接下来,检查cmdOpcode,并发现它与HCI_READ_RSSI匹配 。然后检查事件的状态。现在事件已知,可以使用蓝牙核心规范版本5.0中的信息来解析pReturnParmam 。上述蓝牙核心规范版本5.0 API声明pReturnParam的第一个字节为状态。的蓝牙核心规范5.0版 API指出pReturnParam的第二和第三个字节是句柄。然后检查RSSI以查看它是否对应于所需的连接手柄。继续解析使用蓝牙核心规范版本5.0 API,RSSI值可以通过读取pReturnParam的第四个字节来找到。最后,存储RSSI值。




使用特权

评论回复
6
coshi|  楼主 | 2020-2-2 11:59 | 只看该作者
HCI供应商特定的命令
这些命令在“ TI供应商特定HCI指南”中有说明。对于所有特定于供应商的命令,使用这些命令的机制是相同的。下面的示例演示了如何使用“ TI供应商特定HCI指南” 在应用程序中实现HCI命令。使用的命令是HCI扩展包错误率。

发送HCI供应商特定的命令
1.在TI BLE供应商特定指南中查找命令:



2.使用BLE Stack API Reference中的HCI部分找到实现此命令的BLE Stack函数:HCI_EXT_PacketErrorRateCmd()。

3.使用步骤1中的API,填写参数并从应用程序调用命令。在这种特定情况下,在连接形成后应该调用此命令。第一个参数是一个2字节的connHandle,这个例子是0x0000。第二个参数是读取计数器的1字节命令(HCI_EXT_PER_READ)。因此,使用:

HCI_EXT_PacketErrorRateCmd ( 0 , HCI_EXT_PER_READ );


使用特权

评论回复
7
coshi|  楼主 | 2020-2-2 11:59 | 只看该作者
接收HCI供应商特定事件
  • 在“ TI供应商特定HCI指南”中查找相应的事件



使用特权

评论回复
8
coshi|  楼主 | 2020-2-2 12:00 | 只看该作者
2.如命令API的“对应事件”部分所述,此命令返回“供应商特定命令完成事件”(hciEvt_VSCmdComplete_t),因此在处理HCI_GAP_EVENT_EVENT处理时添加此事件。这在下面进一步详细说明。                static uint8_t SimpleBLEPeripheral_processStackMsg(ICall_Hdr* pMsg)
                {
                   uint8_t safeToDealloc = TRUE;
                   switch (pMsg->event)
                   {
                      case HCI_GAP_EVENT_EVENT:
                      {
                         // Process HCI message
                         switch(pMsg->status)
                         {
                            // Process HCI Vendor Specific Command Complete Event
                            case HCI_VE_EVENT_CODE:
                               {
                                  // Parse Command Complete Event for opcode and status
                                  hciEvt_VSCmdComplete_t* command_complete = (hciEvt_VSCmdComplete_t*)pMsg;
               
                                  // Find which command this command complete is for
                                  switch(command_complete->cmdOpcode)
                                  {
                                     case HCI_EXT_PER:
                                     {
                                        uint8_t status = command_complete->pEventParam[2];
                                        if (status == SUCCESS)
                                        {
                                           uint8_t cmdVal = command_complete->pEventParam[3];
               
                                           if (cmdVal == 1) //if we were reading packet error rate
                                           {
                                              uint16_t numPkts = BUILD_UINT16(command_complete->pEventParam[5], command_complete->pEventParam[4]);
                                              uint16_t numCrcErr = BUILD_UINT16(command_complete->pEventParam[7], command_complete->pEventParam[6]);
                                              uint16_t numEvents = BUILD_UINT16(command_complete->pEventParam[9], command_complete->pEventParam[8]);
                                              uint16_t numMissedEvents = BUILD_UINT16(command_complete->pEventParam[11], command_complete->pEventParam[10]);
               


首先,检查堆栈消息的状态以查看它是什么类型的HCI事件。在这种情况下,它是一个HCI_VE_EVENT_CODE。接下来,将作为消息(pMsg)从堆栈返回的事件转换为hciEvt_VSCmdComplete_t,其定义为:

        typedef struct
        {
           osal_event_hdr_t hdr; uint8 length;
           uint16 cmdOpcode; uint8* pEventParam;
        } hciEvt_VSCmdComplete_t;
通过读取command_complete-> cmdOpcode来检查操作码,并发现它与HCI_EXT_PER匹配。

接下来,解析* pEventParam来提取事件API中定义的参数。前两个字节(图67中以红色显示)是事件操作码(0x1404)。第三个字节是状态。所有供应商特定事件都是这种情况。

从pEventParam的第四个字节开始,从第三个参数开始,使用“TI BLE供应商指南”中的事件API进行解析。所有供应商特定事件都是这种情况。对于此示例,pEventParam的第四个字节对应于cmdVal参数。这在存储器中显示并在下面进一步解释。




通过读取事件参数的第三个字节(command_complete-> pEventParam [2])来检查状态。图67中以黄色显示。

从事件参数(command_complete-> pEventParam [3])的第四个字节开始,事件API指出下一个参数是一个字节的cmdVal。这被检查以验证该事件是否对应于PER计数器的读取。这显示为粉色。

使用事件API继续解析,下一个参数是两个字节的numPkts。这是通过在事件参数的第五和第六个字节中构建一个uint16_t来找到的。这显示为蓝色。以类似的方式,从第七和八个字节的事件参数(绿色显示)中找到numCrcErr。

接下来,从事件参数的第九和第十个字节找到numEvents(以橙色显示)。最后,从事件参数的第十一和第十二个字节找到numMissedEvents(以紫色显示)。



使用特权

评论回复
9
wiba| | 2020-3-1 11:26 | 只看该作者
非常感谢楼主分享

使用特权

评论回复
10
zljiu| | 2020-3-1 11:30 | 只看该作者
非常感谢楼主分享

使用特权

评论回复
11
drer| | 2020-3-1 11:33 | 只看该作者
非常感谢楼主分享

使用特权

评论回复
12
gwsan| | 2020-3-1 11:39 | 只看该作者
非常感谢楼主分享

使用特权

评论回复
13
kxsi| | 2020-3-1 11:43 | 只看该作者
非常感谢楼主分享

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

95

主题

3301

帖子

4

粉丝