【应用笔记】LAT1413+快速开关蓝牙导致设备无广播

1. 问题背景

客户使用 BlueNRG-345MC 开发了一个 BLE 外设,和手机连接。在测试中发现,手机连接上外设之后,不断地在手机上点击蓝牙的开关按钮,造成设备不断地断开、重连;少则几次,多则几十次。点击之后,必然出现 BLE 外设无广播信号的现象。该问题已经得到了解决。本文将展开聊聊该问题的解决过程和思路,并就该问题总结、分享一些 BLE 连接过程的处理经验。

2. 定位问题

拿到该反馈描述后,第一时间和客户沟通了几个问题,明确了大概的方向。沟通的思路按照:硬件问题、软件问题?硬件问题是和设备相关,板子相关、还是芯片相关?软件问题根据设备类型,是和 APP 相关、手机系统相关、BLE 主机固件相关、还是 BLE 外设固件相关这样的思路进行排查。通过以下问题,粗略地进行问题的定位:

“对端设备是什么,如果是手机的话,是否有 APP?“——对端是手机,并且有配套的APP。该问题确定了设备类型,和软件类型。

“该问题是否必现,且稳定复现,问题出现后,状态是否能保持?“——问题稳定复现且必现,而且状态能保持,这是一个重要的依据,由此依据,我们可以进一步发问:

“杀死配套 APP 的后台,用其它手机、第三方 APP(BLE 调试助手等)是否能搜到设备的广播信号“——杀死配套 APP 的后台,确保设备断连、处于广播状态,然后通过第三方的手机、APP 搜索设备的广播,确定当问题出现后,出现异常的是主机方、还是从机方。客户反馈第三方 APP 搜索不到该设备,说明此时从机方出现了异常且保持在异常状态中。

“问题出现后,设备是否还能正常运行“——确定了从机方出现异常后,我们需要进一步定位该异常。该问题可确认问题是局部问题,还是系统问题。如果此时系统还能正常运行(比如,有 LOG 输出,有 LED 闪烁,有按键反应等),就说明是局部问题,系统还没死机。客户反馈系统还正常,这真是一个好消息!蓝牙问题最怕是系统性的问题,即因为系统奔溃,导致的蓝牙奔溃,如果是系统性的问题,那可能性就多很多了,丢给客户的问题就可能包括:

  • “是否和低功耗管理有关,关掉低功耗试试?”
  • “是否和特定板子有关,换块板试试?”
  • “是否和供电稳定性有关,用直流电源试试?电量低是否更容易复现?”……

既已确定了是局部蓝牙的问题,那么,如果对蓝牙的 LL 状态机和基本的 GAP 流程熟悉的话,那基本就可以通过这个问题来定位该问题了:
“请仔细检查下用户层的操作逻辑,是否能确保蓝牙断连时,必能调用使能广播的 API,且拿到成功的状态返回?”——客户拿到该问题后,不知道从何下手,于是,现场支持。

3. BLE 背景知识

话接上文,解决该问题需要对 LL 状态机和 GAP 流程有一定的了解。本章节便先对相关背景知识先做一个补充陈述。
蓝牙链路层(Link Layer)的运转过程可通过一个状态机进行描述。蓝牙从机的状态机简单描述如下:
图1. LL 状态机
在这里插入图片描述
对于该状态机的理解,需要注意以下几点:

  • • 设备断开连接之后,LL 层进入的是 Standby 状态,而不会自动重新发起广播,此时必须由 Host 主动启动广播才能让设备被主机搜索到。
  • • 设备处于 Standby 状态时,必须先进入广播状态,才能由此进入连接状态。对于从机,如果设备不进入广播状态,即使主机发起回连,也不可能被连接成功。
  • • 广播中的设备,当它被上层停止广播、或者被主机连接时,便会退出广播状态。此处需要注意的是,当链路建立,协议栈会将链路建立事件层层上传,其中,就包括 GAP层 。GAP 层在接收到链路建立事件之后,便会开始执行一系列的流程……

这些流程包括,特性交换流程,MTU 交换流程,连接参数更新流程,安全流程(配对流程、绑定流程、加密流程),GATT 服务发现流程等。刚连上那会的几秒钟,是 BLE 外设最繁忙的时间段,也是最容易出现问题的时间段。有经验的工程师,一般都会将一些时间敏感的任务的处理,和这段时间段进行错开。下面的序列图描述了这一过程:
图2. GAP 序列图
在这里插入图片描述

从图中可知,从机协议栈遵循 LL 状态机的运转流程,在三个状态中切换;用户层在断开回调函数中,必须稳妥地开启广播,才能让协议栈从机的状态机按照我们的预期运转。

4. 解决问题

相信通过 BLE 背景知识的介绍,部分人已经大概了解了问题的原因了。到达客户现场调试时,通过蓝牙抓包器、并让客户当场复现问题,我把蓝牙主、从机的空中交互过程记录下来。仔细观察抓包器的记录过程,发现当问题发生时,断开连接的事件出现得非常早期:在链路建立、特性交换流程刚执行完后,即发生了断连。
图3. 蓝牙抓包记录
在这里插入图片描述

仔细检查客户的代码,果然,客户将连接成功的依据放在了 MTU 交换成功之后,即,用户层的蓝牙连接状态,和实际的链路层的连接状态,在快速操作蓝牙开、关的动作之后,脱钩了!该问题可通过下面的序列图描述:

图4. 问题图示
在这里插入图片描述

之所以把蓝牙连接成功的标志,在 MTU 交换成功的回调中置位,客户的想法很简单:用户层需要依据 MTU 的大小,来决定用户层数据包的尺寸,而用户工程师发现,每次蓝牙连接时,MTU 交换完成回调函数都会被执行,于是,想当然的认为可以依据该回调来设置用户层蓝牙的连接标志。

发现了问题的根因后,解决方法也比较简单,把置位连接成功标志的动作,放到连接建立回调函数中即可。

5. 小结

蓝牙协议栈是个分层的协议,当我们说蓝牙已连接时,想表达的意思应该是链路层链路建立,而现实中,很多工程师都把蓝牙已连接理解成了可以收、发数据了。实际上,从蓝牙链路建立,到协议栈可以为用户层收、发数据,中间还差了十万八千里。总而言之,从本文的解题思路出发,我总结以下几点经验:

  • • 用户程序应该深刻理解“蓝牙已连接”的概念, 做好状态管理。
  • • 链路建立后是蓝牙最繁忙的时刻,用户任务处理应尽可能避开该时间段。
  • • 加快链路建立繁忙时间段的方法包括:
    -o 链路建立后,使用较快的连接间隔,并在之后调慢以平衡功耗
    -o 使用 GATT CACHING 特性

本文档参考ST官方的《【应用笔记】LAT1315+串口DMA接收不定长数据的一种方法》文档。
参考下载地址:https://download.csdn.net/download/u014319604/89055623

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/292792.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Entity Framework】创建并配置模型

【Entity Framework】创建并配置模型 文章目录 【Entity Framework】创建并配置模型一、概述二、使用fluent API配置模型三、分组配置四、对实体类型使用EntityTypeConfigurationAttribute四、使用数据注释来配置模型五、实体类型5.1 在模型中包含类型5.2 从模型中排除类型5.3 …

loadbalancer 引入与使用

在消费中pom中引入 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId> </dependency> 请求调用加 LoadBalanced 注解 进行服务调用 默认负载均衡是轮训模式 想要切换…

【数据结构与算法】二叉树的遍历及还原

树形结构 - 有向无环图 树是图的一种。 树形结构有一个根节点树形结构没有回路根节点&#xff1a;A叶子节点&#xff1a;下边没有其他节点了节点:既不是根节点,又不是叶子节点的普通节点树的度:这棵树最多叉的节点有多少叉&#xff0c;这棵树的度就为多少树的深度&#xff1a…

实例、构造函数、原型、原型对象、prototype、__proto__、原型链……

学习原型链和原型对象&#xff0c;不需要说太多话&#xff0c;只需要给你看看几张图&#xff0c;你自然就懂了。 prototype 表示原型对象__proto__ 表示原型 实例、构造函数和原型对象 以 error 举例 图中的 error 表示 axios 抛出的一个错误对象&#xff08;实例&#xff0…

WiFiSpoof for Mac wifi地址修改工具

WiFiSpoof for Mac&#xff0c;一款专为Mac用户打造的网络隐私守护神器&#xff0c;让您在畅游互联网的同时&#xff0c;轻松保护个人信息安全。 软件下载&#xff1a;WiFiSpoof for Mac下载 在这个信息爆炸的时代&#xff0c;网络安全问题日益凸显。WiFiSpoof通过伪装MAC地址&…

C++入门知识详细讲解

C入门知识详细讲解 1. C简介1.1 什么是C1.2 C的发展史1.3. C的重要性1.3.1 语言的使用广泛度1.3.2 在工作领域 2. C基本语法知识2.1. C关键字(C98)2.2. 命名空间2.2 命名空间使用2.2 命名空间使用 2.3. C输入&输出2.4. 缺省参数2.4.1 缺省参数概念2.4.2 缺省参数分类 2.5. …

GRE和MGRE综合实验

实际网段划分 分配IP 1.IP划分 [r1]int g0/0/0 [r1-GigabitEthernet0/0/0]ip add 192.168.1.254 24 Mar 29 2024 16:42:44-08:00 r1 %%01IFNET/4/LINK_STATE(l)[3]:The line protocol IP on the interface GigabitEthernet0/0/0 has entered the UP state. [r1-Gigabi…

飞天使-k8s知识点28-kubernetes散装知识点5-helm安装ingress

文章目录 安装helm添加仓库下载包配置创建命名空间安装 安装helm https://get.helm.sh/helm-v3.2.3-linux-amd64.tar.gztar -xf helm-v3.2.3-linux-amd64.tar.gzcd linux-amd64mv helm /usr/local/bin修改/etc/profile 文件&#xff0c;修改里面内容,然后重新启用export PATH$P…

动态规划-----背包类问题(0-1背包与完全背包)详解

目录 什么是背包问题&#xff1f; 动态规划问题的一般解决办法&#xff1a; 0-1背包问题&#xff1a; 0 - 1背包类问题 分割等和子集&#xff1a; 完全背包问题&#xff1a; 完全背包类问题 零钱兑换II: 什么是背包问题&#xff1f; 背包问题(Knapsack problem)是一种…

Windows-安装infercnv包(自备)

目录 安装基础 ①安装JAGS a,找到适配版本 b&#xff0c;install for me only安装路径 ②安装"rjags"包 ③安装inferCNV 安装基础 版本&#xff1a; R version 4.2.2 (2022-10-31 ucrt) -- "Innocent and Trusting"安装的JAGS版本为JAGS 4.3.1 首…

GPT提示词分享 —— 智能域名生成器

提示词&#x1f447; 我希望你能充当一个聪明的域名生成器。我将告诉你我的公司或想法是什么&#xff0c;你将根据我的提示回复我一份域名备选清单。你只需回复域名列表&#xff0c;而不是其他。域名应该是最多 7-8 个字母&#xff0c;应该简短但独特&#xff0c;可以是朗朗上口…

C易错注意之分支循环,悬空else,短路表达式,函数static

接下来的日子会顺顺利利&#xff0c;万事胜意&#xff0c;生活明朗-----------林辞忧 前言&#xff1a; c语言中一些关于分支循环中continue常混淆&#xff0c;悬空esle问题&#xff0c;短路表达式&#xff0c;static ,extern在使用时稍不注意就会出错的点,接下来我们将介绍…

Monkey工具之fastbot-iOS实践

Monkey工具之fastbot-iOS实践 背景 目前移动端App上线后 crash 率比较高&#xff0c; 尤其在iOS端。我们需要一款Monkey工具测试App的稳定性&#xff0c;更早的发现crash问题并修复。 去年移动开发者大会上有参加 fastbot 的分享&#xff0c;所以很自然的就想到Fastbot工具。…

Lilishop商城(windows)本地部署【docker版】

Lilishop商城&#xff08;windows&#xff09;本地部署【docker版】 部署官方文档&#xff1a;LILISHOP-开发者中心 https://gitee.com/beijing_hongye_huicheng/lilishop 本地安装docker https://docs.pickmall.cn/deploy/win/deploy.html 命令端页面 启动后docker界面 注…

java回溯算法笔记

回溯算法综述 回溯用于解决你层for循环嵌套问题&#xff0c;且不剪枝的回溯完全等于暴力搜索。 回溯算法模板https://blog.csdn.net/m0_73065928/article/details/137062099?spm1001.2014.3001.5501 组合问题&#xff08;startindex避免使用重复元素&#xff09; “不含重复…

一篇讲明白 Hadoop 生态的三大部件

文章目录 每日一句正能量前言01 HDFS02 Yarn03 Hive04 HBase05 Spark及Spark Streaming关于作者推荐理由后记赠书活动 每日一句正能量 黎明时怀着飞扬的心醒来&#xff0c;致谢爱的又一天&#xff0c;正午时沉醉于爱的狂喜中休憩&#xff0c;黄昏时带着感恩归家&#xff0c;然后…

Redis持久化 RDB AOF

前言 redis的十大类型终于告一段落了,下面我们开始redis持久化新篇章 为啥需要持久化呢? 我们知道redis是挡在mysql前面的带刀侍卫 是在内存中的,假如我们的redis宕机了,难道数据直接冲入mysql??? 这显然是不可能的,mysql肯定扛不住这样的场景,所以我们有了redis持久化策略…

Linux 进程信号:产生信号

目录 一、通过终端按键产生信号 1、signal()函数 2、核心转储 3、ulmit命令 二、调用系统函数向进程发信号 1、kill()函数 2、raise()函数 3、abort()函数 三、发送信号的过程 读端关闭、写端继续写入的情况 如何理解软件条件给进程发送信号: 四、软件条件产生信…

【PythonGIS】Python实现批量导出面矢量要素(单个多面矢量->多个单面矢量)

可怜的我周六还在工作&#xff0c;已经很久没更新过博客了&#xff0c;今天正好有空就和大家分享一下。今天给大家带来的是使用Python将包含多个面要素/线要素的矢量批量导出单个要素的矢量&#xff0c;即一个要素一个矢量文件。之前写过多个矢量文件合并成一个矢量文件的博文&…

(一)kafka实战——kafka源码编译启动

前言 本节内容是关于kafka消息中间键的源码编译&#xff0c;并通过idea工具实现kafka服务器的启动&#xff0c;使用的kafka源码版本是3.6.1&#xff0c;由于kafka源码是通过gradle编译的&#xff0c;以及服务器是通过scala语言实现&#xff0c;我们要预先安装好gradle编译工具…