RT-Thread平台 zephyr_polling软件包 Bluenrg2 蓝牙芯片启动流程

描述

RTT zephyr_polling软件包 Bluenrg2 蓝牙芯片启动流程


“开源之夏”“蓝牙HOST协议栈zephyr_polling完善” 项目个人记录

菜鸡参与项目的个人记录

项目软件包地址:RTT_PACKAGE_zephyr_polling

前面已经完成了 SPI 接口的实现,要让 zephyr_polling 在 Bluenrg2 上运行起来,下一步是实现其特殊的芯片启动流程。

 

蓝牙芯片启动流程


在用标准的 HCI 指令控制设备进行蓝牙操作之前,需要提前通过 VS Command 对设备进行配置,只有正确配置好的设备才能正常使用。

芯片产商只出售芯片,并不关注外围电路和具体的产品形态,这些是具体的ODM厂商来实现的。也就是芯片产商提供带HCI蓝牙功能的芯片,ODM设计电路并设计产品,之后通过HCI和芯片进行交互。实际各家ODM产商的需求各不相同,芯片产商为了满足不同客户的需要,并且为了减少和客户的对接,就必然在同一套代码的基础上,需要提供一系列的配置参数来满足不同 ODM 厂商的需要。

配置可以包括:固件烧录(部分没有带 FLASH 的蓝牙芯片每次上电都需要重新烧录最新的固件)、蓝牙地址配置、硬件接口配置(如RF接口,晶振类型等,部分蓝牙芯片需要)、波特率配置(HCI 一般是UART接口,默认是115200)以及芯片需要的由厂商要求的其他参数配置。

此外,对于一些有Flash的芯片,完全可以将配置参数等预烧录到了 Flash 中,使用时完全不需要配置任何参数,直接通过HCI接口操作使用即可。

zephyr_polling 协议栈提供了 Boot 流程接口和 Prepare 流程接口,可以根据实际芯片的需求实现启动配置。

RT-Thread

Boot流程:

完成厂商的初始化流程,如固件下载,蓝牙地址配置等。在 chipset 注册好接口后,协议栈启动时会通过boot_start()回调启动 chipset(指协议栈 chipset 目录下的启动流程代码,下同) 的 Boot 流程,由于操作接口是 HCI,所以一般都是下发一个VS Command,然后根据 VS Event 来进行后续动作,协议栈会通过event_process()回调接口将收到的 event 上报给 chipset,当 chipset 认为操作结束时,通过调用bt_hci_set_boot_ready()接口通知协议栈boot流程结束。

Prepare流程:

部分厂商的参数要求在 HCI_Reset Command 之后进行(意思是它们的 HCI_Reset Command 会清空配置的参数)。为了兼容这类参数形态,HCI_Reset Command 之后还加入了 Prepare 流程。协议栈收到 HCI_Reset 的 Command Complete Event 后会通过prepare_start()回调启动 chipset 的 Prepare 流程,和 Boot 流程一样,协议栈会通过event_process()回调接口将收到的 event 上报给 chipset ,当chipset 认为操作结束时,通过调用bt_hci_set_prepare_ready()接口通知协议栈prepare流程结束。

 

BlueNRG-2 启动流程


查阅 ST 官方提供的手册和例程资料,可以了解到 BlueNRG-2 的启动配置需求。

对于 BlueNRG-2:

Boot 流程:无事务。

Prepare 流程:关闭Host功能;蓝牙地址配置;设置 TX power;GATT配置;GAP配置。

 

BlueNRG-2 启动流程实现


Boot 流程

BlueNRG-2 的 HCI_Reset Command 会清空配置的参数,所以实际的配置放在协议栈的 Prepare 流程中。Boot 流程的回调函数直接调用bt_hci_set_boot_ready()结束流程。


		

1void boot_start(void) { 2    state = STATE_POLLING_BOOTING; 3    // nothing to do 4    bt_hci_set_boot_ready();          //finish boot 5}

Prepare 流程 - 关闭 Host 功能

开发使用的蓝牙模块 X-NUCLEO-BNRG2A1 中的 BLE 本身是一个 SOC,里面集成了 host 的协议栈。厂商 ST 提供了一套 ACI 指令来控制芯片行为,包括 host 的接口。也就是说默认的情况下,这个芯片的 ACL 交互都被接管了,所以需要通过 ACI 命令,关闭 host 行为。需要通过aci_hal_write_config_data里的CONFIG_DATA_LL_WITHOUT_HOST关闭 host。

Prepare 流程第一步,关闭 host:


		

1void prepare_start(void) { 2    state = STATE_POLLING_PREPARING; 3    step = 1; 4    // step 1 close host 5    bluenrg2_config_without_host(); // It can be written only if aci_hal_write_config_data() is the first command after reset. 6}

关闭 host 的指令的 ogf 为0x3f,ocf 为0x00c,参数为2c11。其中,0x2C是关闭 Host 在 CONFIG_DATA 中的 offset。


		

1#define CONFIG_DATA_LL_WITHOUT_HOST         (0x2C) /**< Switch on/off Link Layer only mode. Set to 1 to disable Host. */ 2#define CONFIG_DATA_LL_WITHOUT_HOST_LEN     (1) 3static int bluenrg2_config_without_host() 4{ 5    uint8_t cmd_buffer[CONFIG_DATA_LL_WITHOUT_HOST_LEN + 2]; 6    struct net_buf *buf; 7    cmd_buffer[0] = CONFIG_DATA_LL_WITHOUT_HOST;                //offset 8    cmd_buffer[1] = CONFIG_DATA_LL_WITHOUT_HOST_LEN;            //config len 9    cmd_buffer[2] = 1;                                          //Set to 1 to disable Host 10    uint16_t ogf = 0x3f, ocf = 0x00c; 11    uint16_t opcode = (uint16_t)((ocf & 0x03ff)|(ogf << 10)); 12    buf = bt_hci_cmd_create(opcode, sizeof(cmd_buffer)); 13    if (!buf) 14    { 15        return -ENOBUFS; 16    } 17    net_buf_add_mem(buf, cmd_buffer, sizeof(cmd_buffer)); 18    return bt_hci_cmd_send(opcode, buf); 19}

Prepare 流程 - 蓝牙地址设置

需要通过aci_hal_write_config_data里的CONFIG_DATA_PUBADDR_OFFSET配置蓝牙地址。

配置蓝牙地址的指令的 ogf0x3f,ocf 为0x00c。配置蓝牙地址指令在 CONFIG_DATA 中的 offset 为 0x00,后面跟上地址长度和设置的蓝牙地址。


		

1#define BLE_MAC_ADDR                                                                                2    {                                                                                               3        {                                                                                           4            0xf5, 0x00, 0x00, 0xE1, 0x80, 0x02                                                    5        }                                                                                           6    } 7#define CONFIG_DATA_PUBADDR_OFFSET          (0x00) /**< Bluetooth public address */ 8#define CONFIG_DATA_PUBADDR_LEN             (6) 9static int bluenrg2_config_set_public_addr() 10{ 11    uint8_t cmd_buffer[CONFIG_DATA_PUBADDR_LEN + 2]; 12    struct net_buf *buf; 13    bt_addr_t addr = BLE_MAC_ADDR; 14    cmd_buffer[0] = CONFIG_DATA_PUBADDR_OFFSET;                 //offset 15    cmd_buffer[1] = CONFIG_DATA_PUBADDR_LEN;                    //config len 16    memcpy(cmd_buffer + 2, addr.val, CONFIG_DATA_PUBADDR_LEN);   // addr 17    uint16_t ogf = 0x3f, ocf = 0x00c; 18    uint16_t opcode = (uint16_t)((ocf & 0x03ff)|(ogf << 10)); 19    buf = bt_hci_cmd_create(opcode, sizeof(cmd_buffer)); 20    if (!buf) 21    { 22        return -ENOBUFS; 23    } 24    net_buf_add_mem(buf, cmd_buffer, sizeof(cmd_buffer)); 25    return bt_hci_cmd_send(opcode, buf); 26}

Prepare 流程 - 设置发射功率

配置发射功率的指令的 ogf 为0x3f,ocf 为0x00f。命令参数为是否启用高功率模式(0x00启用普通功率,0x01启用高功率)和功率放大器输出电平(允许的PA电平取决于设备)。

PA_Level 值对应功率 

0: -14 dBm (High Power) 

1: -11 dBm (High Power) 

2: -8 dBm (High Power) 

3: -5 dBm (High Power) 

4: -2 dBm (High Power) 

5: 2 dBm (High Power) 

6: 4 dBm (High Power) 

7: 8 dBm (High Power)


		1static int bluenrg2_set_tx_power_level(uint8_t En_High_Power, uint8_t PA_Level)  2{  3    uint8_t cmd_buffer[2];  4    struct net_buf *buf;  5    cmd_buffer[0] = En_High_Power;      //En_High_Power  6    cmd_buffer[1] = PA_Level;           //config PA_Level  7    uint16_t ogf = 0x3f, ocf = 0x00f;  8    uint16_t opcode = (uint16_t)((ocf & 0x03ff)|(ogf << 10));  9    buf = bt_hci_cmd_create(opcode, sizeof(cmd_buffer)); 10    if (!buf) 11    { 12        return -ENOBUFS; 13    } 14    net_buf_add_mem(buf, cmd_buffer, sizeof(cmd_buffer)); 15    return bt_hci_cmd_send(opcode, buf); 16} Prepare 流程 - GATT 配置

GATT 初始化的指令的 ogf 为0x3f,ocf 为0x101,没有其它参数。


		

1static int  bluenrg2_gatt_init(void) 2{ 3    uint16_t ogf = 0x3f, ocf = 0x101; 4    uint16_t opcode = (uint16_t)((ocf & 0x03ff)|(ogf << 10)); 5    return bt_hci_cmd_send(opcode, NULL); 6}

Prepare 流程 - GAP 配置

初始化 GAP 层。注册GAP服务,并设置标准 GAP 服务特性:设备名称、Appearance、外围设备首选连接参数(仅限外围设备)。

GAP 配置的指令的 ogf 为0x3f,ocf 为0x08a。配置为外围设备,如果需要用做其他角色,需要修改此处;不启用隐私策略(为保护地址不被窃取,进行地址加密/解密,并周期更新);设置设备名字长度。

privacy: 

0x00: Privacy disabled 

0x01: Privacy host enabled 

0x02: Privacy controller enabled


			

1#define GAP_PERIPHERAL_ROLE                     (0x01) 2#define GAP_BROADCASTER_ROLE                    (0x02) 3#define GAP_CENTRAL_ROLE                        (0x04) 4#define GAP_OBSERVER_ROLE                       (0x08) 5#define privacy_enabled                         (0x00) 6#define device_name_char_len                    (0x08) 7static int bluenrg2_gap_init() 8{ 9    uint8_t cmd_buffer[3]; 10    struct net_buf *buf; 11    cmd_buffer[0] = GAP_PERIPHERAL_ROLE;    //role 12    cmd_buffer[1] = privacy_enabled;        //privacy 13    cmd_buffer[2] = device_name_char_len;   //device_name_char_len 14    uint16_t ogf = 0x3f, ocf = 0x08a; 15    uint16_t opcode = (uint16_t)((ocf & 0x03ff)|(ogf << 10)); 16    buf = bt_hci_cmd_create(opcode, sizeof(cmd_buffer)); 17    if (!buf) 18    { 19        return -ENOBUFS; 20    } 21    net_buf_add_mem(buf, cmd_buffer, sizeof(cmd_buffer)); 22    return bt_hci_cmd_send(opcode, buf); 23}

启动事件处理

对于启动流程的返回响应,需要由event_process()回调进行判断和推进。这里为了方便,只对CMD_COMPLETE事件进行判断处理,推进 Prepare 流程进行。

GAP 设置完成后调用bt_hci_set_prepare_ready()结束流程。


			

1void event_process(uint8_t event, struct net_buf *buf) 2{ 3    if(state == STATE_POLLING_PREPARING) // boot do nothing 4    { 5        if (event == BT_HCI_EVT_CMD_COMPLETE)  //only complete 6        { 7            printk("prepare_event_process, step: %d ", step); 8            switch (step) 9            { 10            case 1//close host just now 11                bluenrg2_config_set_public_addr();  //step2  set_public_addr 12                step = 2; 13                break; 14            case 2: 15                bluenrg2_set_tx_power_level(14);  //step3  set_public_addr 16                step = 3; 17                break; 18            case 3: 19                bluenrg2_gatt_init();               //step4  gatt_ini 20                step = 4; 21                break; 22            case 4: 23                bluenrg2_gap_init();                //step5  gap_ini 24                step = 5; 25                break; 26            case 5: 27                bt_hci_set_prepare_ready();          //finish prepare 28                step = 0; 29                break; 30            } 31        } 32    } 33}

启动流程注册

将上述实现的启动流程的函数指针打包到bt_hci_chipset_driver结构体中,供协议栈调用注册。


			

1static const struct bt_hci_chipset_driver chipset_drv = { 2        init_work, boot_start, prepare_start, event_process, 3}; 4// public drv API 5const struct bt_hci_chipset_driver *bt_hci_chipset_impl_local_instance(void) 6{ 7    return &chipset_drv; 8}

 

验证


完成 HCI 接口的时候虽然成功运行了 Beacon 例程,但 Beacon 例程是不需要进行 chipset 启动配置流程的(运行时启用的是common空白回调)。运行外设的心率例程验证 Bluenrg2 蓝牙芯片启动流程。


			

1  | / 2- RT -     Thread Operating System 3 / |      5.0.1 build Sep 20 2023 22:16:27 4 2006 - 2022 Copyright by RT-Thread team 5do components initialization. 6initialize rti_board_end:0 done 7initialize stm32l4_hw_lptim_init:0 done 8initialize finsh_system_init:0 done 9msh >zephyr 10zephyr_polling_init  11bt_init_hci_driver  12SPI_init_process device_name: spi10, spi_name: spi1, rate: 1000000, databits: 8, LSB_MSB: 1, Master_Slave: 0, CPOL: 0, CPHA: 1 13SPI_init_process cs_pin_num: 1, irq_pin_num: 0 14hci_driver_open, SPI_config_finish 15I: (bt_hci_core)hci_init():3230: work start. 16msh >prepare_event_process, step: 1 17prepare_event_process, step: 2 18prepare_event_process, step: 3 19prepare_event_process, step: 4 20prepare_event_process, step: 5 21I: (bt_hci_core)hci_init_end():3205: work end. 22E: (bt_smp)smp_self_test():5695: smp_self_test start 23I: (bt_hci_core)bt_dev_show_info():3008: Identity: 02:8000:00:f5 (public) 24I: (bt_hci_core)bt_dev_show_info():3042: HCI: version 5.2 (0x0b) revision 0x1222, manufacturer 0x0030 25I: (bt_hci_core)bt_dev_show_info():3044: LMP: version 5.2 (0x0b) subver 0x0015 26Bluetooth initialized 27Advertising successfully started 28Connected 29BAS Notifications enabled 30HRS notifications enabled


		

 


		

prepare_event_process 步骤的日志输出正常,设备连接、电池服务、心率服务正常。


		

RT-Thread


		

 


		

———————End——————

 

 

RT-Thread

点击阅读原文进入官网

 


原文标题:RT-Thread平台 zephyr_polling软件包 Bluenrg2 蓝牙芯片启动流程

文章出处:【微信公众号:RTThread物联网操作系统】欢迎添加关注!文章转载请注明出处。


打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分