当前位置: 首页 > news >正文

Telink BLE SDK软件架构

标准 BLE SDK 软件架构

在上图所⽰的架构中,BLE协议栈分为Host和Controller两部分。

  • Controller 作为 BLE 底层协议,包括PhysicalLayer(PHY)和LinkLayer(LL)。Host Controller Interface (HCI)是Controller 与 Host 的唯⼀通信接⼝,Controller 与 Host 所有的数据交互都通过该接⼝完成。
  • Host 作为 BLE 上层协议,协议上有 Logic Link Control and Adaption Protocol(L2CAP)、Attribute Protocol(ATT)、Security Manager Protocol(SMP),Profile 包括 Generic Access Profile(GAP)、Generic Attribute Profile(GATT)
  • 应⽤层(APP)包含user⾃⼰相关应⽤代码和各种service对应的Profile,user 通过GAP去控制访问 Host。Host 通过 HCI 与 Controller 完成数据交互,如下图所⽰。

(1) BLE Host 通过 HCI cmd 去操作设置Controller,这些 HCI cmd 对应本章后⾯将要介绍的controller API。

(2) Controller 通过 HCI 向 host 上报各种 HCI event,本章也会具体介绍。

(3) Host 将需要发送给对⽅设备的数据通过 HCI 传送到 Controller,Controller 将数据直接丢到 Physical Layer 进⾏发送。

(4) Controller 在 Physical Layer 收到的 RF 数据,先判断是属于 Link Layer 的数据还是 Host 的数据:如果 是Link Layer 的数据,直接处理数据;如果是Host的数据,则通过HCI将数据传到Host。

Telink BLE SDK 软件架构

Telink BLE SDK ⽀持标准的 BLE controller,包括 HCI、PHY(Physical Layer)和 LL(link layer)。

Telink BLE SDK 包含 Link Layer 的五种标准状态(standby、advertising、scanning、initiating、connection), conneciton 状态下的 Slave role 和 Master role 也都⽀持。B85m BLE Single Connection SDK 中的 Slave role 和Master role 都只是 single connection,即 Link Layer 只能维持⼀个连接,⽆法同时多个Slave/Master 或者 Slave 和 Master 同时存在。

SDK 上的B85mhci 是⼀个BLEslave 的 controller,需要和另外⼀个运⾏ BLE Host 的 MCU 协调⼯作形成⼀ 个标准的BLESlave系统,架构图如下。

Link Layer connection 状态同时⽀持 single connection 的 Slave 和 Master,那么 B85m hci 实际也可以作为 BLE master controller 使⽤,但实际对于⼀个 BLE host 运⾏在较复杂的系统(如 linux/android)来说,单⼀ 连接的Master controller 只能连接⼀个设备,⼏乎是没有意义的,所以SDK在B85mhci上并没有将master role 的初始化放进去。

Telink BLE Slave

Telink BLE SDK 在 BLE host 上,只对Slave部分的stack完全⽀持;对于Master⽆法做到完全⽀持,因为SDP (service discovery)太复杂。

当user 只需要使⽤标准的BLEslave时,TelinkBLESDK运⾏Host(slave部分)+标准的Controller,实际的 协议栈架构会对上⾯标准的结构做⼀些简化处理,使得整个SDK的系统资源开销(包括sram、运⾏时间、功耗 等)最⼩,其架构如下图所⽰。SDK中B85mblesample、B85mremote、B85mmodule都是基于该架构。

图中实⼼箭头所⽰的数据交互是user可以通过各种接⼝来操作控制的,会提供userAPI。空⼼箭头是协议栈内 部完成的数据交互,user⽆法参与。

Controller 部分 HCI 仍然是与 Host 的数据通信接⼝(和L2CAP层对接),但不是唯⼀的接⼝,APP应⽤层也可 以直接与LinkLayer 进⾏数据交互。PowerManagement(PM)低功耗管理单元被内嵌到Linklayer,应⽤层 可以调⽤PM相关接⼝进⾏功耗管理的设置。

考虑到效率,应⽤层与Host的数据交互不通过GAP来访问控制,协议栈在ATT、SMP和L2CAP都提供了相 关接⼝,可以和应⽤层直接交互。但是Host的事件需要通过GAP层和应⽤层交互。

BLE Controller

BLE controller 包括 Physical Layer、Link Layer、HCI 和 Power Management。 Telink BLE SDK 对 Physical Layer(对应 driver ⽂件中的 rf.h 的 c ⽂件)完全封装到library 中,user 不需要了 解。Power Management 将在本⽂档后⾯的章节中详细介绍,本章只稍微提⼀下,不做过多介绍。 本章只介绍LinkLayer和HCI,且由于HCI主要是interface,其实现的功能也都是为了操作LinkLayer和获取 Link Layer 的数据,所以重点详细介绍Linklayer,并在介绍LinkLayer 和 API 的过程中对HCI相关interface ⼀⼀描述。

Link Layer 状态机

协议BLE 5.0

Telink BLE SDK Link Layer 状态机如下图所⽰

Telink BLE SDK Link Layer 状态机和 BLE spec 定义的⼀致,拥有 5 种基本状态:Idle(Standby)、Scanning、 Advertising、Initiating、Connection。将 Conneciton 状态区分为 Slave Role 和 Master Role

图中PowerManagement并不是LL的⼀种状态,⽽是功能模块,表⽰的是SDK只对Advertising和Connection Slave Role 进⾏了低功耗处理;Idle state 如果需要低功耗,user 在应⽤层调⽤相关API 可以完成;其他⼏个state,SDK 没有做低功耗管理,user也⽆法在应⽤层实现低功耗。

基于上⾯5种状态,stack/ble/ll/ll.h 中定义了状态机的命名。其中ConnSlaveRole 和 ConnMasterRole 时状态 名都是BLS_LINK_STATE_CONN。

#define BLS_LINK_STATE_IDLE         0
#define BLS_LINK_STATE_ADV          BIT(0) 
#define BLS_LINK_STATE_SCAN         BIT(1) 
#define BLS_LINK_STATE_INIT         BIT(2) 
#define BLS_LINK_STATE_CONN         BIT(3) 

Link Layer 状态机的切换都在BLEstack 底层⾃动完成,所以user在应⽤层⽆法去修改状态,只能获取当前状 态,调⽤下⾯API即可,返回值为上⾯5种状态中的1种。

u8 blc_ll_getCurrentState(void);

Link Layer 状态机组合应用

Telink BLE SDK Link Layer 完整的⽀持所有状态,但在设计上很灵活,每⼀个状态都封装成为⼀个模块,默认 情况下只有最基本的Idle模块,user通过添加模块的⽅式去搭建⾃⼰的状态机组合,从⽽实现不同的应⽤。⽐ 如user 需要的应⽤是BLEslave,那么只需要添加Advertising 模块和ConnSlaveRole 模块就可以了,剩下的 Scanning/Initiating 等模块没有被配置进来。这样的设计的⽬的是节省codesize 和ram_code,不需要使⽤的 状态的相关代码不会被编译进来。

MCU 的初始化是必须的,API如下:

void blc_ll_initBasicMCU (void);

Idle 模块的添加API 如下,这个是必须的,所有的BLE应⽤都需要初始化。

void blc_ll_initStandby_module (u8 *public_adr);

其他⼏个状态(Scanning、Advertising、Initiating、Slave Role、Master Role Single Connection)对应模块的 初始化API分别如下:

void blc_ll_initAdvertising_module(u8 *public_adr);void blc_ll_initScanning_module(u8 *public_adr);void blc_ll_initInitiating_module(void);void blc_ll_initConnection_module(void);void blc_ll_initSlaveRole_module(void);void blc_ll_initMasterRoleSingleConn_module(void);

上⾯API中实参public_adr 都是 BLE public mac address 的指针。

Idle + Advertising

上图所⽰,只初始化Idle和Advertising 模块,使⽤最基本的Advertising 功能实现的应⽤如beacon等,单⽅ 向⼴播产品信息。 Link Layer 状态机模块初始化代码为:

 u8 mac_public[6] = {……}; 
blc_ll_initBasicMCU(); 
blc_ll_initStandby_module(mac_public); 
blc_ll_initAdvertising_module(mac_public);

Idle 和 Advertising 状态的切换通过 bls_ll_setAdvEnable 来实现。

Idle + Scanning

如下图所⽰,只初始化Idle和Scanning模块,使⽤最基本的Scanning功能实现beacon等产品⼴播信息的扫 描发现。 Link Layer 状态机模块初始化代码为:

u8 mac_public[6] = {……}; 
blc_ll_initBasicMCU(); 
blc_ll_initStandby_module(tbl_mac); 
blc_ll_initScanning_module( tbl_mac);

Idle 和 Scanning 状态的切换通过blc_ll_setScanEnable 来实现。

Idle + Advertising + ConnSlaveRole

上图所⽰为⼀个基本的BLEslave应⽤的LinkLayer 状态机组合,SDK中b85mhci/b85m ble sample/b85m remote/b85m module 都是基于该状态机组合。

Link Layer 状态机模块初始化代码为:

u8 mac_public[6] = {……};blc_ll_initBasicMCU();blc_ll_initStandby_module(mac_public);blc_ll_initAdvertising_module(mac_public);blc_ll_initConnection_module();blc_ll_initSlaveRole_module();

该状态机组合下,状态变化情况描述如下。

(1) MCU 上电后,进⼊Idle state。Idle state 时将 adv Enable,Link Layer 切换到 Advertising State;adv Disable 时,回到 Idle state。

        Adv Enable 和 Disable 通过下⾯ API bls_ll_setAdvEnable 来控制。

        上电后,Linklayer默认处于Idle状态,⼀般需要在user_init⾥⾯将AdvEnable,进⼊Advertisingstate。

(2) Link Layer 处于 Idle state 时,Physical Layer 不进⾏任何 RF 相关动作,不收包也不发包。 (3) Link Layer 处于 Advertising state 时,在⼴播 channel 上发送⼴播包。若 master 收到⼴播包,并发送 conneciton request,Link Layer 收到这个 connection request 后,响应并建⽴连接,Link Layer 进⼊ ConnSlaveRole。

(4) Link Layer 处于 ConnSlaveRole 时,有三种情况会回到 Idle State 或者 Advertising state:

  • master 向 slave 发送 terminate 命令,断开连接。slave 收到 terminate 命令,退出 ConnSlaveRole。
  • slave 向 master 发送 terminate 命令,主动断开连接,退出ConnSlaveRole。
  • slave 的 RF 收包异常或 master 发包异常,导致 slave ⻓时间收不到包,触发 BLE 的 connection supervision timeout,退出 ConnSlaveRole。

Link layer 的 ConnSlaveRole 退出该 state 时,根据 Adv 是否被 Enable 切换到不同 state:若 Adv 被 enable, Link Layer 重新回到 Advertising state;若 Adv 被 Disable,Link Layer 回到 Idle state。Adv 处于 Enable 或者 Disable 取决于 user 在应⽤层最后⼀次调⽤bls_ll_setAdvEnable 时设置的值。

Link Layer 时序

结合该BLESDK的irq_handler 和 main_loop 来说明 Link layer 在各状态的⼯作时序

_attribute_ram_code_ void irq_handler(void){……irq_blt_sdk_handler ();……}void main_loop (void)
{///////////////////// BLE entry ////////////////////////////blt_sdk_main_loop();////////////////////// UI entry ////////////////////////////……}

BLE entry 部分 blt_sdk_main_loop 函数负责处理 BLE 协议栈相关的数据和事件。UI entry是user写⾃⼰的应 ⽤代码的地⽅。

Idle State 时序

当Link Layer 处于 Idle state 时,Link Layer 和 Physical Layer 没有任何任务要处理,blt_sdk_main_loop 函数 完全不起作⽤,也不会产⽣任何中断。可以认为UI entry占据了整个main_loop的时序。

Advertising State 时序

Advertising state 时序图如上所⽰。每⼀个advinterval 时间内Link Layer 触发⼀个Advevent。⼀个典型的3 个advchannel 都发包的 Adv event 会在 channel 37、38、39 上都发送⼀个⼴播包。每发⼀个⼴播包之后都 进⼊收包状态,等待master可能的回包,回包有两种:⼀个是scanrequest,收到这个包后再发送⼀个scan response 作为回复;另⼀个是connectreqeust,收这个包后和master建⽴ble连接,进⼊Connectionstate Slave Role。

user 在 main_loop 的 UI entry 部分的 code 执⾏会在图中所⽰的UItask/suspend 部分执⾏,这部分时间全部 可以⽤来做UItask,如果需要低功耗的话,可以将多余的时间⽤来sleep(suspend/deepsleepretention) 以降 低功耗。

在Advertising state,blt_sdk_main_loop 函数没有太多要处理的任务,只是触发⼏个跟Adv相关的⼏个回调事 件。包括BLT_EV_FLAG_ADV_DURATION_TIMEOUT、BLT_EV_FLAG_SCAN_RSP、BLT_EV_FLAG_CONNECT 等。

Scanning State 时序

Scanning state 时序图如上所⽰,Scan interval 是由 API blc_ll_setScanParameter 设置。整个 Scan interval 对⼀个channel 进⾏收包,没有将Scan window 设计到 SDK ⾥,所以 blc_ll_setScanParameter 中对 Scan window 的设置SDK是不处理的。

每个Scaninterval 结束后,切换到下⼀个收包的Channel,开始新⼀轮的Scaninterval。切换channel的动作 是interrupt 触发的,在 irq 中完成该动作,其执⾏时间⾮常短。 Scanning interval 上,Scan 状态 PHY 层⼀直处于 RX 状态,靠 MCU 硬件去实现收包操作,所以软件上的 timing 都留给了 UI task。

在Scaninterval 上收到正确的BLEpacket后,将收包数据先缓存在软件RXfifo中(对应code中的my_fifo_t blt_rxfifo),blt_sdk_main_loop 函数会检查软件 RX fifo 中是否有数据,如果发现正确的 adv 数据会通过 event“HCI_SUB_EVT_LE_ADVERTISING_REPORT”将其 report 给 BLE host。

Initiating State 时序

Initiating state 时序图如上所⽰,和 Scanning state 时序是⼀样的,不同点是 Scan interval 由 API blc_ll_createConnection 设置。整个 Scan interval 对⼀个 channel 进⾏收包,没有将 Scan window 设计到 SDK ⾥,所以blc_ll_createConnection 中对 Scan window 的设置 SDK 是不处理的。

每个Scaninterval 结束后,切换到下⼀个收包的Channel,开始新⼀轮的Scaninterval。切换channel的动作 是interrupt 触发的,在 irq 中完成该动作,其执⾏时间⾮常短。

Scanning state 中 BLE controller 将收到的 adv packet report 给 BLE host,⽽ Initiating state 不会 report adv 给BLE host,它只是 Scan 到由blc_ll_createConnection 指定的设备后,发送 connection_request 并建⽴连 接,然后LinkLayer 进⼊ConnMasterRole。

Conn State Slave Role 时序

ConnSlaveRole 时序图如上所⽰。每⼀个conninterval 开始的时候,Link Layer 进⾏⼀次BLE 的RF包收发过 程:先让PHY进⼊收包状态,收到master的包后发送⼀个ack包回复,若有more data,则继续收master 包并回复,这个过程简称为brx event。

在该BLESDK中,根据软硬件的⼯作分配,每个brx过程分为3个阶段:

(1) brx start 阶段

当master 发包的时间快要到来时,会由systemtick irq 触发进⼊ brx start 阶段,在这个中断⾥ MCU 设置 PHY 的BLE状态机进⼊brx状态,底层硬件做好收发包的相关准备,然后退出中断irq。

(2) brx working 阶段

brx start 结束后,MCU 退出irq 后,底层硬件进⼊收包状态,并⾃动完成收发包的所有⼯作,不需要软件任何 的参与,这个过程称为brxworking阶段。

(3) brx post 阶段

收发包完成后,brxworking 结束,同样由systemtick irq 触发进⼊中断执⾏brxpost 阶段。这个阶段主要是 协议栈根据brxworking 阶段收发包的情况对BLE的⼀些数据和时序进⾏相关的处理。

上⾯三个阶段中brx start和brx post 都是中断完成,⽽brx working阶段不需要软件的参与,此时UItask可 以正常执⾏(注意brxworking阶段RX、TX、系统定时器中断等处理函数以外的时隙是可以跑UItask的)。brx working 时间内,硬件需要进⾏收发包,所以不能进sleep(suspend/deepsleep retention)。

整个conn interval 内除去 brx 过程的时间,可以⽤来做UI task,如果需要低功耗的话,可以将多余的时间⽤ 来sleep(suspend/deepsleep retention) 以降低功耗。

在ConnSlaveRole,blt_sdk_main_loop 需要处理 brx 过程收到的数据。brx working 过程中,实际是在 RX 接 收中断irq处理中将硬件收到的master数据包拷⻉出来,这些数据并不会⽴刻实时处理,⽽是将数据缓存到软 件RXfifo 中(对应code中的my_fifo_tblt_rxfifo)。blt_sdk_main_loop 函数会检查软件 RX fifo 中是否有数 据,只要有数据就去处理。

blt_sdk_main_loop 对数据包的处理包括:

(1) 数据包的解密

(2) 数据包的解析

解析的数据若发现是属于master发给LinkLayer的控制命令,⽴即执⾏该命令,若是master发给Host层的 数据,则会通过HCI接⼝将数据丢到L2CAP层处理。

Conn State Slave role 时序保护

ConnSlaveRole,每个 interval 需要⼀个收发包事件,也就是上⾯的 Brx Event。B85m SDK 中,Brx Event 完 全是由中断触发的,所以MCU系统总中断需要⼀直被打开。如果user在Connstate的⼀些任务时间较⻓且必须把系统总中断关闭(⽐如擦除Flash),就会造成BrxEvent被停掉,BLE的时序很快就乱掉,最终连接断开。对于这种情况SDK中提供了⼀套保护机制,让user去停掉BrxEvent却不破坏BLE的时序,user需要严 格根据这个机制来操作。相关API如下:


int bls_ll_requestConnBrxEventDisable(void);
void bls_ll_disableConnBrxEvent(void);
void bls_ll_restoreConnBrxEvent(void);

调⽤bls_ll_requestConnBrxEventDisable 来申请关掉 Brx Event。

1) 该 API 返回值若为0,表⽰当前不接受⽤⼾的申请,即此时不能停掉BrxEvent。在Connstate时的Brx working 阶段,不能接受申请,返回值为 0,⼀定要等到⼀个完整的BrxEvent 结束后,在剩余的UI task/ suspend 时间内才会接受申请。

2) 该 API 返回⾮0值表⽰可以接受申请,返回的值是允许停掉BrxEvent的时间,单位为ms。该事件值有三 种情况:

A. 若当前Link Layer为Advertising state或Idle state,返回值为0xffff,即没有Brx Event,⽤⼾关闭系 统中断的时间随便多⻓都可以。

B. 若当前为Conn state,收到了master的update map或update connection parameter且还没有到更新的时间点时,返回时间为更新的时间点减去当前时间。即停掉Brx Event的时间不能超过更新的时间点,否则会造成 后⾯所有包收不到,最终断开连接。

C. 若当前为Conn state,且没有master的更新请求,返回值为当前connection supervision timeout值的⼀ 半。⽐如当前timeout为1S,返回值为500ms。

user 调⽤上⾯的API 申请停掉Brx Event,若返回值对应的时间(ms),⾜够⾃⼰的任务运⾏时间,即可进⾏该任务。在该任务执⾏之前,调⽤APIbls_ll_disableConnBrxEvent 停掉 Brx Event。任务结束后,调⽤ API bls_ll_restoreConnBrxEvent 重新开启 Brx Event 并修复 BLE 时序。 参考使⽤⽅法如下。其中具体时间的判断,以测试到的实际任务时间为准。

User 在应⽤层发送数据时(⽐如调⽤blc_gatt_pushHandleValueNotify),应该先检查⼀下当前 Link Layer 还 有多少TXfifo可⽤。 下⾯API⽤于判断当前TXfifo被占⽤了多少个,注意不是剩余多少个可⽤。 u8 blc_ll_getTxFifoNumber (void);

⽐如TXfifonumber 默认为16时,user可⽤为14个,所以该API返回的值只要⼩于14,就是可⽤的:返回 13 表⽰还有1个可⽤,返回0则表⽰还有14个可⽤。

http://www.dtcms.com/a/511899.html

相关文章:

  • 计算机毕设java医院挂号系统 基于Java的医院智能挂号与信息管理系统 Java医院挂号及医疗信息综合平台
  • 上海市500强企业名单单页面优化
  • 【0443】signalfd + epoll 完成事件监听+指定信号处理(演示demo)
  • 湛江有没有做网站的算卦网站哪里可以做
  • 布局具身智能时代(上):深兰科技“具身视觉导航大脑”技术的商业化探索
  • test002
  • RTPENGINE redis 测试
  • 在Ubuntu中安装Docker
  • 佛山市专注网站建设平台网站制作二级网页怎么做
  • 百度收录情况查询南通seo公司网站
  • 【MySQL】慢查寻的发现和解决优化(思维导图版)
  • gbase8s之.net8连接8s之mysql模式(windows)demo
  • 【AI】大模型之深度估计
  • 7.1 EXTI工作原理
  • LazyLLM教程 | 第11讲:性能优化指南:从冷启动到响应加速你的RAG
  • windows后渗透中常用的信息收集命令
  • 初始化node项目express,项目结构介绍
  • Optuna - 自动调参利器python实例
  • 新网站做优化要准备什么合肥网站建设哪个公司做得比较好
  • 提供服务好的网站制作网站怎么做会员系统
  • 绍兴网站建设推广宁夏建设管理局网站
  • 【面向小白】git rebase全面总结,什么时候用rebase
  • Kubernates的部署(从安装到实践)
  • C++ 11
  • (一)Flutter 插件项目demo预览图
  • 两学一做 答题 网站好看到让人久久不忘的电影
  • iOS混淆实战:多工具组合完成 IPA 混淆与加固(iOS混淆|IPA加固|无源码混淆|Ipa Guard 实战)
  • 完整网站开发视频教程wordpress网页图片加载很慢
  • 软考高级-系统架构设计师历年案例专题一:软件架构设计
  • SQL入门:分页查询-原理、优化与实战