0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

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

冬至子 来源:paradox 作者:paradox 2023-09-27 11:19 次阅读

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

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

配置可以包括:固件烧录(部分没有带 FLASH 的蓝牙芯片每次上电都需要重新烧录最新的固件)、蓝牙地址配置、硬件接口配置(如RF接口,晶振类型等,部分蓝牙芯片需要)、波特率配置(HCI 一般是UART接口,默认是115200)以及芯片需要的由厂商要求的其他参数配置。
此外,对于一些有Flash的芯片,完全可以将配置参数等预烧录到了 Flash 中,使用时完全不需要配置任何参数,直接通过HCI接口操作使用即可。

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

1.jpg

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()结束流程。

void boot_start(void) {
state = STATE_POLLING_BOOTING;
// nothing to do
bt_hci_set_boot_ready(); //finish boot
}

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:

void prepare_start(void) {
state = STATE_POLLING_PREPARING;
step = 1;
// step 1 close host
bluenrg2_config_without_host(); // It can be written only if aci_hal_write_config_data() is the first command after reset.
}
关闭 host 的指令的 ogf 为0x3f,ocf 为0x00c,参数为2c11。其中,0x2C是关闭 Host 在 CONFIG_DATA 中的 offset。

#define CONFIG_DATA_LL_WITHOUT_HOST (0x2C) /**< Switch on/off Link Layer only mode. Set to 1 to disable Host. */
#define CONFIG_DATA_LL_WITHOUT_HOST_LEN (1)
static int bluenrg2_config_without_host()
{
uint8_t cmd_buffer[CONFIG_DATA_LL_WITHOUT_HOST_LEN + 2];
struct net_buf *buf;
cmd_buffer[0] = CONFIG_DATA_LL_WITHOUT_HOST; //offset
cmd_buffer[1] = CONFIG_DATA_LL_WITHOUT_HOST_LEN; //config len
cmd_buffer[2] = 1; //Set to 1 to disable Host
uint16_t ogf = 0x3f, ocf = 0x00c;
uint16_t opcode = (uint16_t)((ocf & 0x03ff)|(ogf << 10));
buf = bt_hci_cmd_create(opcode, sizeof(cmd_buffer));
if (!buf)
{
return -ENOBUFS;
}
net_buf_add_mem(buf, cmd_buffer, sizeof(cmd_buffer));
return bt_hci_cmd_send(opcode, buf);
}

Prepare 流程 - 蓝牙地址设置
需要通过aci_hal_write_config_data里的CONFIG_DATA_PUBADDR_OFFSET配置蓝牙地址。

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

#define BLE_MAC_ADDR
{
{
0xf5, 0x00, 0x00, 0xE1, 0x80, 0x02
}
}
#define CONFIG_DATA_PUBADDR_OFFSET (0x00) /**< Bluetooth public address */
#define CONFIG_DATA_PUBADDR_LEN (6)
static int bluenrg2_config_set_public_addr()
{
uint8_t cmd_buffer[CONFIG_DATA_PUBADDR_LEN + 2];
struct net_buf *buf;
bt_addr_t addr = BLE_MAC_ADDR;
cmd_buffer[0] = CONFIG_DATA_PUBADDR_OFFSET; //offset
cmd_buffer[1] = CONFIG_DATA_PUBADDR_LEN; //config len
memcpy(cmd_buffer + 2, addr.val, CONFIG_DATA_PUBADDR_LEN); // addr
uint16_t ogf = 0x3f, ocf = 0x00c;
uint16_t opcode = (uint16_t)((ocf & 0x03ff)|(ogf << 10));
buf = bt_hci_cmd_create(opcode, sizeof(cmd_buffer));
if (!buf)
{
return -ENOBUFS;
}
net_buf_add_mem(buf, cmd_buffer, sizeof(cmd_buffer));
return bt_hci_cmd_send(opcode, buf);
}
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)

static int bluenrg2_set_tx_power_level(uint8_t En_High_Power, uint8_t PA_Level)
{
uint8_t cmd_buffer[2];
struct net_buf *buf;
cmd_buffer[0] = En_High_Power; //En_High_Power
cmd_buffer[1] = PA_Level; //config PA_Level
uint16_t ogf = 0x3f, ocf = 0x00f;
uint16_t opcode = (uint16_t)((ocf & 0x03ff)|(ogf << 10));
buf = bt_hci_cmd_create(opcode, sizeof(cmd_buffer));
if (!buf)
{
return -ENOBUFS;
}
net_buf_add_mem(buf, cmd_buffer, sizeof(cmd_buffer));
return bt_hci_cmd_send(opcode, buf);
}
Prepare 流程 - GATT 配置
GATT 初始化的指令的 ogf 为0x3f,ocf 为0x101,没有其它参数。

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

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

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

privacy:
0x00: Privacy disabled
0x01: Privacy host enabled
0x02: Privacy controller enabled

#define GAP_PERIPHERAL_ROLE (0x01)
#define GAP_BROADCASTER_ROLE (0x02)
#define GAP_CENTRAL_ROLE (0x04)
#define GAP_OBSERVER_ROLE (0x08)
#define privacy_enabled (0x00)
#define device_name_char_len (0x08)
static int bluenrg2_gap_init()
{
uint8_t cmd_buffer[3];
struct net_buf *buf;
cmd_buffer[0] = GAP_PERIPHERAL_ROLE; //role
cmd_buffer[1] = privacy_enabled; //privacy
cmd_buffer[2] = device_name_char_len; //device_name_char_len
uint16_t ogf = 0x3f, ocf = 0x08a;
uint16_t opcode = (uint16_t)((ocf & 0x03ff)|(ogf << 10));
buf = bt_hci_cmd_create(opcode, sizeof(cmd_buffer));
if (!buf)
{
return -ENOBUFS;
}
net_buf_add_mem(buf, cmd_buffer, sizeof(cmd_buffer));
return bt_hci_cmd_send(opcode, buf);
}

启动事件处理
对于启动流程的返回响应,需要由event_process()回调进行判断和推进。这里为了方便,只对CMD_COMPLETE事件进行判断处理,推进 Prepare 流程进行。
GAP 设置完成后调用bt_hci_set_prepare_ready()结束流程。

void event_process(uint8_t event, struct net_buf *buf)
{
if(state == STATE_POLLING_PREPARING) // boot do nothing
{
if (event == BT_HCI_EVT_CMD_COMPLETE) //only complete
{
printk("prepare_event_process, step: %dn", step);
switch (step)
{
case 1: //close host just now
bluenrg2_config_set_public_addr(); //step2 set_public_addr
step = 2;
break;
case 2:
bluenrg2_set_tx_power_level(1, 4); //step3 set_public_addr
step = 3;
break;
case 3:
bluenrg2_gatt_init(); //step4 gatt_ini
step = 4;
break;
case 4:
bluenrg2_gap_init(); //step5 gap_ini
step = 5;
break;
case 5:
bt_hci_set_prepare_ready(); //finish prepare
step = 0;
break;
}
}
}
}

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

static const struct bt_hci_chipset_driver chipset_drv = {
init_work, boot_start, prepare_start, event_process,
};
// public drv API
const struct bt_hci_chipset_driver *bt_hci_chipset_impl_local_instance(void)
{
return &chipset_drv;
}

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

| /

RT - Thread Operating System
/ | 5.0.1 build Sep 20 2023 22:16:27
2006 - 2022 Copyright by RT-Thread team
do components initialization.
initialize rti_board_end:0 done
initialize stm32l4_hw_lptim_init:0 done
initialize finsh_system_init:0 done
msh >zephyr
zephyr_polling_init
bt_init_hci_driver
SPI_init_process device_name: spi10, spi_name: spi1, rate: 1000000, databits: 8, LSB_MSB: 1, Master_Slave: 0, CPOL: 0, CPHA: 1
SPI_init_process cs_pin_num: 1, irq_pin_num: 0
hci_driver_open, SPI_config_finish
I: (bt_hci_core)hci_init():3230: work start.
msh >prepare_event_process, step: 1
prepare_event_process, step: 2
prepare_event_process, step: 3
prepare_event_process, step: 4
prepare_event_process, step: 5
I: (bt_hci_core)hci_init_end():3205: work end.
E: (bt_smp)smp_self_test():5695: smp_self_test start
I: (bt_hci_core)bt_dev_show_info():3008: Identity: 02:80:e1:00:00:f5 (public)
I: (bt_hci_core)bt_dev_show_info():3042: HCI: version 5.2 (0x0b) revision 0x1222, manufacturer 0x0030
I: (bt_hci_core)bt_dev_show_info():3044: LMP: version 5.2 (0x0b) subver 0x0015
Bluetooth initialized
Advertising successfully started
Connected
BAS Notifications enabled
HRS notifications enabled
prepare_event_process 步骤的日志输出正常,设备连接、电池服务、心率服务正常。

1.jpg

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

    关注

    17

    文章

    344

    浏览量

    45479
  • UART接口
    +关注

    关注

    0

    文章

    123

    浏览量

    15068
  • ACL
    ACL
    +关注

    关注

    0

    文章

    59

    浏览量

    11876
  • Flash存储
    +关注

    关注

    0

    文章

    38

    浏览量

    8239
  • RTThread
    +关注

    关注

    7

    文章

    129

    浏览量

    40523
收藏 人收藏

    评论

    相关推荐

    RTT_Zephyr_Polling BlueNRG2 SPI使用说明

    在RT-Thread平台下,利用 BlueNRG2 蓝牙芯片运行 RTT_Zephyr_Polling 协议栈。使用 SPI 作为 HCI 传输方式。
    的头像 发表于 09-21 14:54 733次阅读
    <b class='flag-5'>RTT_Zephyr_Polling</b> <b class='flag-5'>BlueNRG2</b> SPI使用说明

    RTT平台zephyr_polling软件包SPI Bluenrg2芯片宕机问题与修复

    项目的代码测试完成之后,准备收尾时,出现了问题。清除掉开发过程中用来调试的print打印之后,zephyr_polling 的 HCI 突然不能正常工作了,之前测试可用的 zephyr_polling 中的各个例程都不再能运行。
    的头像 发表于 09-25 17:08 788次阅读
    <b class='flag-5'>RTT</b>平台<b class='flag-5'>zephyr_polling</b><b class='flag-5'>软件包</b>SPI <b class='flag-5'>Bluenrg2</b><b class='flag-5'>芯片</b>宕机问题与修复

    如何用Ubuntu qemu跑zephyr_polling蓝牙

    进入 RT-Thread online packages → IoT - internet of things 目录即可看到 zephyr_polling软件包,勾选软件包
    的头像 发表于 09-28 11:24 1370次阅读
    如何用Ubuntu qemu跑<b class='flag-5'>zephyr_polling</b>的<b class='flag-5'>蓝牙</b>?

    ST蓝牙芯片Bluenrg

    有没有正在玩St的BlueNrg蓝牙芯片的???有没有遇到过程序log看到已经广播,但是手机搜不到蓝牙;在蓝牙给手机上传数据时出现Blue
    发表于 08-15 15:37

    如何使用RTT Studio配置at软件包来连接wifi模块?

    如何使用RTT Studio配置at软件包来连接wifi模块?
    发表于 02-16 07:47

    分享一种基于littlevgl2rtt软件包的RGB屏幕接口优化方案

    StudioOS版本:4.0.3开发板:Art-Pi + 正点原子4.3寸RGB屏软件包:Littlevgl2rtt(latest)温馨提示:下面的优化方案是基于该软件包的优化,如果是自己一直lvgl的不再此
    发表于 06-07 14:57

    SPI驱动屏幕移植LVGL软件包具体流程

    , send_data, RT_NULL,2);}二、移植lvgl(一)、添加lvgl软件包首先打开rtthread setting,点击右侧的缩进,打开后,选择软件包,再将多媒体
    发表于 07-08 15:09

    RTThread Studio的芯片支持使用说明

    介绍本仓库为RTThread Studio的芯片支持,目前暂时支持52832及52840的rtt完整版下载地址导入教程使用说明创建RTT工程选择
    发表于 08-04 10:48

    主要介绍NimBLE软件包的使用说明

    Host 层,还需要搭配外接蓝牙 Control 芯片使用。RT-Thread Studio 工程中配置使用 NimBLE进入工程 RT-Thread Settings 界面, 点击添加软件包
    发表于 08-18 10:22

    rtt有支持多个文件压缩的软件包

    rtt有支持多个文件压缩的软件包么,比如tar指令,或者有那个大佬实现了多文件压缩的源码可以分享一下么?
    发表于 11-15 10:53

    怎样使用SDK中的Beacon示例对BLUENRG2进行重新编程呢?

    我希望使用 BLUENRG-M2 模块构建一个带有 BLUENRG2 的项目。我购买了一块 X-NUCLEO-BNRG2A1 板开始使用,并将该板上的 SWDIO、SWDCLK、NRESET、VDD
    发表于 01-03 10:00

    浅析Zephyr在ESP32上的启动流程

    理解Zephyr在一款soc上的启动流程,有利于分析和调试开机过程卡死,驱动异常等的问题。因此在上手一款新的soc时掌握Zephyr在其上面的启动
    的头像 发表于 06-07 17:04 4507次阅读

    RTT zephyr_polling SPI Bluenrg2数据传输测试

    RTT 那边的 Kconfig 配置完成,项目的基本开发内容就完成了。然后再对协议栈在 Bluenrg2 芯片上采用 SPI 作为 HCI 的数据传输进行测试。
    的头像 发表于 09-25 16:25 561次阅读
    <b class='flag-5'>RTT</b> <b class='flag-5'>zephyr_polling</b> SPI <b class='flag-5'>Bluenrg2</b>数据传输测试

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

    RTT zephyr_polling软件包 Bluenrg2 蓝牙芯片
    的头像 发表于 09-27 18:40 418次阅读
    RT-Thread平台 <b class='flag-5'>zephyr_polling</b><b class='flag-5'>软件包</b> <b class='flag-5'>Bluenrg2</b> <b class='flag-5'>蓝牙</b><b class='flag-5'>芯片</b><b class='flag-5'>启动</b><b class='flag-5'>流程</b>

    RTT平台zephyr_polling软件包SPI Bluenrg2丢包问题排查

    在对协议栈在 Bluenrg2 芯片上采用 SPI 作为 HCI 的数据传输进行测试的时候,发现存在丢包问题。
    的头像 发表于 10-23 15:41 239次阅读
    <b class='flag-5'>RTT</b>平台<b class='flag-5'>zephyr_polling</b><b class='flag-5'>软件包</b>SPI <b class='flag-5'>Bluenrg2</b>丢包问题排查