Zephyr 精确数据总线错误,BLE bt_uuid_to_str 和坏魔法

问题描述 投票:0回答:1

我正在宣传一项主要的 BLE 服务。使用 nRF android 应用程序一切正常。另一个扫描设备想要找到广告、连接并获取 GATT 服务列表并列出它们的 UUID。扫描和连接工作正常。我确信我已连接到我的设备而不是其他东西。 Discovery 初始化为:

    static struct bt_gatt_discover_params pars;
    pars.func = gattDiscoveryCb;
    pars.type = BT_GATT_DISCOVER_PRIMARY;

    if (bt_gatt_discover(connection, &pars) != 0) {
        LOG_ERR("BLE GATT discovery error");
        return;
    }

这里没有错误,发现开始。我理解(我希望)文档here

params->type
表明我正在发现什么样的东西(必须是BT_GATT_DISCOVER_PRIMARY,因为发现的初始化方式),然后
attr->user_data
struct bt_gatt_service_val
,并且
 uuid
其中有我现在要打印的内容。我在互联网上看到了很多示例,zephyr SDK 文件夹中也有很多示例(例如 ./zephyr/subsys/bluetooth/audio/vcp_vol_ctlr.c)用于执行相同的操作。该过程将 user_data 转换为正确的结构,然后使用
bt_uuid_to_str
从 uuid 生成一个字符串。听起来很简单:

uint8_t gattDiscoveryCb(struct bt_conn *conn, const struct bt_gatt_attr *attr, struct bt_gatt_discover_params *params) {
    char uuid_str[BT_UUID_STR_LEN];
    if (params->type == BT_GATT_DISCOVER_PRIMARY) {
        struct bt_gatt_service_val *service = (struct bt_gatt_service_val *)attr->user_data;
        bt_uuid_to_str(service->uuid, uuid_str, sizeof(uuid_str));

        LOG_INF("Primary service UUID: %s", uuid_str);

    } 

    return BT_GATT_ITER_CONTINUE;
}

然而,在 bt_uuid_to_str 线上,整个事情爆炸了,它说:

00> [00:00:00.400,054] <err> os: ***** BUS FAULT *****
00> [00:00:00.400,054] <err> os:   Precise data bus error
00> [00:00:00.400,085] <err> os:   BFAR Address: 0xef8008f3[0m
00> [00:00:00.400,085] <err> os: r0/a1:  0xef8008f3  r1/a2:  0x20005448  r2/a3:  0x00000025
00> [00:00:00.400,115] <err> os: r3/a4:  0xef8008f3 r12/ip:  0x00000000 r14/lr:  0x00010e49
00> [00:00:00.400,115] <err> os:  xpsr:  0x21000000
00> [00:00:00.400,146] <err> os: Faulting instruction address (r15/pc): 0x00013962
00> [00:00:00.400,177] <err> os: >>> ZEPHYR FATAL ERROR 25: Unknown error on CPU 0
00> [00:00:00.400,207] <err> os: Current thread: 0x20001d60 (unknown)
00> [00:00:01.627,502] <err> fatal_error: Resetting system[0m

不幸的是我不明白发生了什么。任何帮助将不胜感激!

更新:可能很多人都怀疑

attr == NULL
是悲伤的,但却是事实。但为什么呢?

bluetooth-lowenergy zephyr-rtos nrf-connect
1个回答
0
投票

总线错误是尝试使用空指针(就好像它指向数据一样)的结果。 this文档未能清楚地解释的是,当发现某些东西时...或当某些东西发现时,会调用发现回调。:D(最好的工程...)提示和关键的一句话在this页面,谈论回调函数:

“如果发现过程已完成,将调用此回调,并将 attr 设置为 NULL。”

因此

params->type
attr->user_data
之间的关系并不像文档所暗示的那么简单,因为调用回调时可能会使用
params->type
BT_GATT_DISCOVER_PRIMARY
attr
NULL

除非通过返回

BT_GATT_ITER_STOP
来停止发现,否则将调用回调:

  • 每个发现的项目一次,将
    attr->user_data
    设置为相应的事物
  • 在发现过程结束时,当没有更多项目可供发现时,将
    attr
    设置为 NULL

还值得一提的是,传入的

bt_gatt_discover_params
结构体是通过 bt_gatt_discover() 函数调用进行
修改
的:当发现项目时,
start_handle
将被更改。 (不要尝试将此值用于任何有用的事情!发现的项目的句柄不存在)此行为意味着根据用例,必须在连续的
start_handle
调用之间一遍又一遍地设置
bt_gatt_discover()

另一个有趣(令人困惑)的地方是发现功能的文档给出了可能发现的项目类型的后面:主要服务,包括服务,特征,描述符。这是由传入的

type
bt_gatt_discover_params
成员控制的。(分别为 BT_GATT_DISCOVER_PRIMARY、BT_GATT_DISCOVER_INCLUDE、BT_GATT_DISCOVER_CHARACTERISTIC、BT_GATT_DISCOVER_DESCRIPTOR)。回调函数的 documentation 指出
param->type
的值保持不变。然而,回调函数的页面列出了
params->type
的另外两个可能值:BT_GATT_DISCOVER_STD_CHAR_DESC 和 BT_GATT_DISCOVER_ATTRIBUTE。 (Attiubute 非常有趣,因为可能发现的每个项目都是一个属性。事实上,当发现属性时,所有内容都已找到......)这必定意味着
bt_gatt_discover()
函数文档缺少两种可能的类型。

最后我想指出的是回调中

attr->user_data
的类型。回调的文档在表中指出,当发现描述符或属性时,
attr->user_data
为 NULL。这不是真的。如果是 CCC(可能还有 CEP、SCC 和 CPF,甚至可能是其他),描述符和属性发现类型都会在
struct bt_gatt_scc
中返回
attr->user_data
。另一方面,使用
BT_GATT_DISCOVER_STD_CHAR_DESC
类型发现这些结构应该正确返回,却什么也没发现。

© www.soinside.com 2019 - 2024. All rights reserved.