From 312aaf28e618fb1492fe8852ba42c314d54b5351 Mon Sep 17 00:00:00 2001 From: Lenoyan <642842715@qq.com> Date: Mon, 11 Jul 2022 13:52:41 +0000 Subject: [PATCH 01/14] =?UTF-8?q?=E6=96=B0=E5=BB=BA=20nimble-docs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rt-thread-standard/packages-manual/nimble-docs/.keep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/.keep diff --git a/rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/.keep b/rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/.keep new file mode 100644 index 0000000..e69de29 -- Gitee From 2125f35f8754ba64398d8d6c26e099b85f75512b Mon Sep 17 00:00:00 2001 From: Lenoyan <642842715@qq.com> Date: Mon, 11 Jul 2022 13:54:42 +0000 Subject: [PATCH 02/14] =?UTF-8?q?=E6=96=B0=E5=BB=BA=20figures?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rt-thread-standard/packages-manual/nimble-docs/figures/.keep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/figures/.keep diff --git a/rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/figures/.keep b/rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/figures/.keep new file mode 100644 index 0000000..e69de29 -- Gitee From 58526567b2a84ebeb9541dad91e364a38b69f25e Mon Sep 17 00:00:00 2001 From: Lenoyan <642842715@qq.com> Date: Mon, 11 Jul 2022 13:56:17 +0000 Subject: [PATCH 03/14] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20NimBLE=20HCI=20?= =?UTF-8?q?=E5=88=86=E6=9E=90=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...I \345\261\202\345\210\206\346\236\220.md" | 261 ++++++++++++++++++ 1 file changed, 261 insertions(+) create mode 100644 "rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/figures/NimBLE HCI \345\261\202\345\210\206\346\236\220.md" diff --git "a/rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/figures/NimBLE HCI \345\261\202\345\210\206\346\236\220.md" "b/rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/figures/NimBLE HCI \345\261\202\345\210\206\346\236\220.md" new file mode 100644 index 0000000..cc9da8a --- /dev/null +++ "b/rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/figures/NimBLE HCI \345\261\202\345\210\206\346\236\220.md" @@ -0,0 +1,261 @@ +# NimBLE HCI 层分析 + +本文主要分析了 [Apache NimBLE](https://github.com/apache/mynewt-nimble) v1.5 版本的 BLE HCI 层设计,并分析了官方仓库自带 UART 对接例程;关于 BLE 层次结构可以先看一下这篇[参考文档](https://supperthomas-wiki.readthedocs.io/en/latest/ble/00_ble_introduce/BLE_introduce.html#id2)。 + +## NimBLE 目录结构 + +``` +NimBLE + ├───apps /* Bluetooth 示例应用程序 */ + ├───docs /* 官方文档及 API 说明 */ + ├───ext + ├───nimble + │ ├───controller /* Controller 实现 */ + │ ├───doc /* 当前包含 transport 层说明文档 */ + │ ├───drivers /* Nordic 系列 Phy 驱动 */ + │ ├───host /* Host Stack(主机控制器)实现 */ + │ ├───include + │ ├───src + │ └───transport /* HCI 传输抽象层 */ + └───porting /* OS 抽象层及系统配置 */ +``` + +- 观察目录,可以看出 NimBLE 是实现了 Host 与 Controller 分离的,在[官方介绍](https://github.com/apache/mynewt-nimble)中也有说明。 +- nimble 的 Host 可以跑在任一芯片上;Controller 则限制比较多,需要有特殊的硬件以及驱动支持。 +- `nimble/controller` 则是 Controller 相关代码; `nimble/host` 对应 Host 代码; `nimble/transport` 就是 HCI 层代码;这一版本 `nimble/doc` 下还包含了 HCI 层的说明文档 `transport.md`。 +- 顺带一提,porting 目录下是 OS 抽象层及系统配置; rt-thread 的移植就实现在 `porting/npl` 下。 + +## NimBLE HCI 层 + +> 主机控制接口层(Host Controller Interface,简写 HCI):HCI是可选的,主要用于2颗芯片实现BLE协议栈的场合(一个当作 Host 一个当作 Controller),用来规范两者之间的通信协议和通信命令等。 + +NimBLE HCI 层主要是了解 `nimble/transport` 下的内容。首先看一下官方文档 `nimble/doc/transport.md` 中对 transport 层的说明,主要看下面这张图: + +![hci_interface](image/hci_interface.png) + +HCI 层包括这4接口:Host 从 Controller 端接收接口 `ble_transport_to_hs_evt` 和 `ble_transport_to_hs_acl`;以及 Host 向 Controller 发送接口 `ble_transport_to_ll_cmd` 和 `ble_transport_to_ll_acl`。 + +在目录下,官方流出的接口定义主要包含在下面几个文件中: + +``` +transport + └───inlucde + ├───nimble + │ └───transport + │ └───monitor.h + ├───transport_impl.h + └───transport.h +``` + +其中比较重要的是 `transport_impl.h` 文件,从名字也可以看出这是一个需要实现的接口定义文件,其主要内容如下: + +```c++ +/* Init functions to be implemented for transport acting as HS/LL side */ +extern void ble_transport_ll_init(void); +extern void ble_transport_hs_init(void); + +/* APIs to be implemented by HS/LL side of transports */ +extern int ble_transport_to_ll_cmd_impl(void *buf); +extern int ble_transport_to_ll_acl_impl(struct os_mbuf *om); +extern int ble_transport_to_hs_evt_impl(void *buf); +extern int ble_transport_to_hs_acl_impl(struct os_mbuf *om); +``` + +这些接口在 `transport\include\nimble\transport\monitor.h` 中被引用: + +```c++ +static inline int +ble_transport_to_ll_cmd(void *buf) +{ + return ble_transport_to_ll_cmd_impl(buf); +} + +static inline int +ble_transport_to_ll_acl(struct os_mbuf *om) +{ + return ble_transport_to_ll_acl_impl(om); +} + +static inline int +ble_transport_to_hs_evt(void *buf) +{ + return ble_transport_to_hs_evt_impl(buf); +} + +static inline int +ble_transport_to_hs_acl(struct os_mbuf *om) +{ + return ble_transport_to_hs_acl_impl(om); +} +``` + +看完这个文件,大概明白了,之前官方文档图中提到的 HCI 4个接口,在这里与对应的 *_impl() 接口绑定了起来。而 *impl() 接口就是官方提供给开发者具体实现对接的接口。 + +由于 Host 和 Contoller 是双向交互的,所以发送与接收 HCI 包接口是要完整实现的,也就是大多数情况下上述 4 个 *impl() 接口都需要全部实现。 + + + +## 分析 UART 对接 HCI 层官方例程 + +官方提供了一个使用 UART 对接 HCI 层的例程,源码文件为 `nimble/transport/uart/src/hci_uart.c` + +首先找到熟悉的接口:代码中显式实现了 `ble_transport_to_hs_evt_impl` 以及 `ble_transport_to_hs_acl_impl` ,这两个接口中基本上就是使用 uart 向 host 发送数据包,涉及到某个板子 uart 发送数据的具体细节,这里不过多关注。 + +看完上面两个接口,其实 HCI 中向 Host 发送数据包功能算实现完了,且当前文件中没有实现其他的 impl 接口,很容易能想到,这是写的 Controller 端的 HCI 层代码。 + +有了这个定性信息,可以开始分析如何从 uart 中接收 Host 层发来的数据包。 + +通过 uart 初始化函数找到 uart 接收回调函数: + +```c++ +// uart 初始化函数 +rc = hal_uart_init_cbs(MYNEWT_VAL(BLE_TRANSPORT_UART_PORT), + hci_uart_tx_char, NULL, + hci_uart_rx_char, NULL); +``` +```c++ +// uart 接收回调函数 +static int hci_uart_rx_char(void *arg, uint8_t data) +{ + hci_h4_sm_rx(&hci_uart_h4sm, &data, 1); + return 0; +} +``` + +可以看到每接收一个字符,都使用 `hci_h4_sm_rx` 进行接收。该函数声明在 `transport\common\hci_h4\include\nimble\transport\hci_h4.h` 文件下,是关于 H4 的一个函数,大概看一下具体定义,接收字符后有一个组帧判断的过程。看一下 `hci_h4.h` 下比较关键的两个接口: + +```c++ +void hci_h4_sm_init(struct hci_h4_sm *h4sm, + const struct hci_h4_allocators *allocs, + hci_h4_frame_cb *frame_cb); + +int hci_h4_sm_rx(struct hci_h4_sm *h4sm, const uint8_t *buf, uint16_t len); +``` + +`hci_h4_sm_init()` 中出现了一个 `hci_h4_frame_cb *frame_cb` 参数,这是一个函数指针参数,初步猜测用于回调函数的注册。且在 + +`hci_uart.c` 代码中,也找到了 `hci_h4_sm_init()` 相关调用: + +```c++ +244: hci_h4_sm_init(&hci_uart_h4sm, &hci_h4_allocs_from_hs, hci_uart_frame_cb) +``` + +这里将 `hci_uart_frame_cb` 注册成了回调函数,源码中定义如下: + +```c++ +static int +hci_uart_frame_cb(uint8_t pkt_type, void *data) +{ + switch (pkt_type) { + case HCI_H4_CMD: + return ble_transport_to_ll_cmd(data); + case HCI_H4_ACL: + return ble_transport_to_ll_acl(data); + default: + assert(0); + break; + } + return -1; +} +``` + +`hci_uart_frame_cb` 基本上是对一个完整的 HCI 包的处理,根据不同的类型使用 `ble_transport_to_ll_cmd` 和 `ble_transport_to_ll_acl` 传输给 Link Layer 层( Link Layer 是 Controller 上的一个层次,更加确定这是 Controller 上的 HCI 层实现 )。 + +结合 `hci_uart.c` 中对 `hci_h4_sm` 的使用,以及对 `hci_h4_sm` 相关接口源码的分析,`hci_h4_sm` 其实是官方提供的一个类似保证包完整性的东西,用于判断一帧完整的 HCI 数据包,并且提供组包完成回调函数的机制。 + +看到这里,大概脉络应该已经捋清楚了。这是一个 Controller 上的 UART HCI 层对接实现: + +1. 向 Host 发送 HCI 包:主要通过显式实现 `ble_transport_to_hs_evt_impl` 以及 `ble_transport_to_hs_acl_impl` 接口实现,具体何时被调用,协议栈已经自动处理好。 +2. 从 Host 接收 HCI 包:主要是使用的 hci_h4 中的组包接口,hci_h4_sm 即一个组包的状态机实例,通过 `hci_h4_sm_rx` 接收 uart 接收到的字符,在判断 hci 包完整接收时调用提前注册好的 回调函数 `hci_h4_frame_cb` 。 `hci_h4_frame_cb` 里则实现了将 uart 接收到的包传递给 LL 层,进而 Controller 可以对 Host 传下来的命令或数据做出响应动作。 + + + +## 完整的 HCI 层实现 + +### Controller 使用 UART 做 HCI 层数据传输 + +开始说到无论在什么情况下都要完成 HCI 层中 4个主要接口的实现,当前 `hci_uart.c` 中只找到了两个接口的实现,还有另外两个接口在哪呢。使用全局搜索在 `nimble\controller\src\ble_ll.c` 下找到了另外两个接口的实现: + +```c++ +/* Transport APIs for LL side */ + +int +ble_transport_to_ll_cmd_impl(void *buf) +{ + return ble_ll_hci_cmd_rx(buf, NULL); +} + +int +ble_transport_to_ll_acl_impl(struct os_mbuf *om) +{ + return ble_ll_hci_acl_rx(om, NULL); +} +``` + +因为目前默认在 Controller 端实现 HCI 层,剩下未实现的两个接口在 Controller 源码下实现了。 + + + +### Host 使用 UART 做 HCI 层数据传输 + +那么假设当前需要实现 Host 端的 HCI 层,且还是需要使用 UART 对接。那么需要实现对接 UART 的接口应该刚好和 `hci_uart.c` 中相反。 + +需要在对接源码中,实现 `ble_transport_to_ll_cmd_impl` 和 `ble_transport_to_ll_acl_impl` 发送接口,具体同样也是使用 UART 发送包。相应的,在 `nimble\host\src\ble_hs.c` 下找到了以下两个接口的实现: + +```c++ +/* Transport APIs for HS side */ + +int +ble_transport_to_hs_evt_impl(void *buf) +{ + return ble_hs_hci_rx_evt(buf, NULL); +} + +int +ble_transport_to_hs_acl_impl(struct os_mbuf *om) +{ + return ble_hs_rx_data(om, NULL); +} +``` + +也就实现了 Host端 HCI 层的完整搭建。 + + + +- 在使用 UART 对接 HCI 层时,是默认当前环境只跑了 Host 或 Controller 中的一端,因此 `nimble\controller\src\ble_ll.c` 和 + + `nimble\host\src\ble_hs.c` 不会同时参与编译,自然也不会引起一些 `*impl()` 接口重复定义的错误。 + + + +### 不需要其他接口进行 HCI 传输 + +当 Host 与 Controller 跑在同一环境中,不需要对接具体的数据传输接口, `nimble\controller\src\ble_ll.c` 和 + + `nimble\host\src\ble_hs.c` 同时参与编译,此时无需再编写额外的代码,即可完整实现整个 HCI 层。 + + + +## 总结 + +在较早的版本中,NimBLE 对接 HCI 层需要实现以下接口([参考文档](https://github.com/Jackistang/HM/blob/rtthread/docs/HCI_Tramsport.md)): + +```c++ +int ble_hci_trans_hs_cmd_tx(uint8_t *cmd); +int ble_hci_trans_hs_acl_tx(struct os_mbuf *om); +void ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *cmd_cb, + void *cmd_arg, + ble_hci_trans_rx_acl_fn *acl_cb, + void *acl_arg); + +uint8_t *ble_hci_trans_buf_alloc(int type); +void ble_hci_trans_buf_free(uint8_t *buf); +int ble_hci_trans_set_acl_free_cb(os_mempool_put_fn *cb, void *arg); + +int ble_hci_trans_reset(void); +``` + +可以看出来有一些麻烦,除了处理数据传输方向,还有处理数据包的内存申请与释放,实现起来较为复杂。 + +当前版本中官方对 HCI 层进行了重构,在 `transport.c` 中统一处理了数据包的内存申请与释放;让开发者专注于处理数据的发送与接收方式,并且提供了 H4 类型的 HCI 包接收工具,更加方便开发者的对接使用。 + -- Gitee From a1fb4738956bed16a9d7a02be971653682089f2d Mon Sep 17 00:00:00 2001 From: Lenoyan <642842715@qq.com> Date: Mon, 11 Jul 2022 13:57:34 +0000 Subject: [PATCH 04/14] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20rt?= =?UTF-8?q?-thread-version/rt-thread-standard/packages-manual/nimble-docs/?= =?UTF-8?q?figures/NimBLE=20HCI=20=E5=B1=82=E5=88=86=E6=9E=90.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...I \345\261\202\345\210\206\346\236\220.md" | 261 ------------------ 1 file changed, 261 deletions(-) delete mode 100644 "rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/figures/NimBLE HCI \345\261\202\345\210\206\346\236\220.md" diff --git "a/rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/figures/NimBLE HCI \345\261\202\345\210\206\346\236\220.md" "b/rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/figures/NimBLE HCI \345\261\202\345\210\206\346\236\220.md" deleted file mode 100644 index cc9da8a..0000000 --- "a/rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/figures/NimBLE HCI \345\261\202\345\210\206\346\236\220.md" +++ /dev/null @@ -1,261 +0,0 @@ -# NimBLE HCI 层分析 - -本文主要分析了 [Apache NimBLE](https://github.com/apache/mynewt-nimble) v1.5 版本的 BLE HCI 层设计,并分析了官方仓库自带 UART 对接例程;关于 BLE 层次结构可以先看一下这篇[参考文档](https://supperthomas-wiki.readthedocs.io/en/latest/ble/00_ble_introduce/BLE_introduce.html#id2)。 - -## NimBLE 目录结构 - -``` -NimBLE - ├───apps /* Bluetooth 示例应用程序 */ - ├───docs /* 官方文档及 API 说明 */ - ├───ext - ├───nimble - │ ├───controller /* Controller 实现 */ - │ ├───doc /* 当前包含 transport 层说明文档 */ - │ ├───drivers /* Nordic 系列 Phy 驱动 */ - │ ├───host /* Host Stack(主机控制器)实现 */ - │ ├───include - │ ├───src - │ └───transport /* HCI 传输抽象层 */ - └───porting /* OS 抽象层及系统配置 */ -``` - -- 观察目录,可以看出 NimBLE 是实现了 Host 与 Controller 分离的,在[官方介绍](https://github.com/apache/mynewt-nimble)中也有说明。 -- nimble 的 Host 可以跑在任一芯片上;Controller 则限制比较多,需要有特殊的硬件以及驱动支持。 -- `nimble/controller` 则是 Controller 相关代码; `nimble/host` 对应 Host 代码; `nimble/transport` 就是 HCI 层代码;这一版本 `nimble/doc` 下还包含了 HCI 层的说明文档 `transport.md`。 -- 顺带一提,porting 目录下是 OS 抽象层及系统配置; rt-thread 的移植就实现在 `porting/npl` 下。 - -## NimBLE HCI 层 - -> 主机控制接口层(Host Controller Interface,简写 HCI):HCI是可选的,主要用于2颗芯片实现BLE协议栈的场合(一个当作 Host 一个当作 Controller),用来规范两者之间的通信协议和通信命令等。 - -NimBLE HCI 层主要是了解 `nimble/transport` 下的内容。首先看一下官方文档 `nimble/doc/transport.md` 中对 transport 层的说明,主要看下面这张图: - -![hci_interface](image/hci_interface.png) - -HCI 层包括这4接口:Host 从 Controller 端接收接口 `ble_transport_to_hs_evt` 和 `ble_transport_to_hs_acl`;以及 Host 向 Controller 发送接口 `ble_transport_to_ll_cmd` 和 `ble_transport_to_ll_acl`。 - -在目录下,官方流出的接口定义主要包含在下面几个文件中: - -``` -transport - └───inlucde - ├───nimble - │ └───transport - │ └───monitor.h - ├───transport_impl.h - └───transport.h -``` - -其中比较重要的是 `transport_impl.h` 文件,从名字也可以看出这是一个需要实现的接口定义文件,其主要内容如下: - -```c++ -/* Init functions to be implemented for transport acting as HS/LL side */ -extern void ble_transport_ll_init(void); -extern void ble_transport_hs_init(void); - -/* APIs to be implemented by HS/LL side of transports */ -extern int ble_transport_to_ll_cmd_impl(void *buf); -extern int ble_transport_to_ll_acl_impl(struct os_mbuf *om); -extern int ble_transport_to_hs_evt_impl(void *buf); -extern int ble_transport_to_hs_acl_impl(struct os_mbuf *om); -``` - -这些接口在 `transport\include\nimble\transport\monitor.h` 中被引用: - -```c++ -static inline int -ble_transport_to_ll_cmd(void *buf) -{ - return ble_transport_to_ll_cmd_impl(buf); -} - -static inline int -ble_transport_to_ll_acl(struct os_mbuf *om) -{ - return ble_transport_to_ll_acl_impl(om); -} - -static inline int -ble_transport_to_hs_evt(void *buf) -{ - return ble_transport_to_hs_evt_impl(buf); -} - -static inline int -ble_transport_to_hs_acl(struct os_mbuf *om) -{ - return ble_transport_to_hs_acl_impl(om); -} -``` - -看完这个文件,大概明白了,之前官方文档图中提到的 HCI 4个接口,在这里与对应的 *_impl() 接口绑定了起来。而 *impl() 接口就是官方提供给开发者具体实现对接的接口。 - -由于 Host 和 Contoller 是双向交互的,所以发送与接收 HCI 包接口是要完整实现的,也就是大多数情况下上述 4 个 *impl() 接口都需要全部实现。 - - - -## 分析 UART 对接 HCI 层官方例程 - -官方提供了一个使用 UART 对接 HCI 层的例程,源码文件为 `nimble/transport/uart/src/hci_uart.c` - -首先找到熟悉的接口:代码中显式实现了 `ble_transport_to_hs_evt_impl` 以及 `ble_transport_to_hs_acl_impl` ,这两个接口中基本上就是使用 uart 向 host 发送数据包,涉及到某个板子 uart 发送数据的具体细节,这里不过多关注。 - -看完上面两个接口,其实 HCI 中向 Host 发送数据包功能算实现完了,且当前文件中没有实现其他的 impl 接口,很容易能想到,这是写的 Controller 端的 HCI 层代码。 - -有了这个定性信息,可以开始分析如何从 uart 中接收 Host 层发来的数据包。 - -通过 uart 初始化函数找到 uart 接收回调函数: - -```c++ -// uart 初始化函数 -rc = hal_uart_init_cbs(MYNEWT_VAL(BLE_TRANSPORT_UART_PORT), - hci_uart_tx_char, NULL, - hci_uart_rx_char, NULL); -``` -```c++ -// uart 接收回调函数 -static int hci_uart_rx_char(void *arg, uint8_t data) -{ - hci_h4_sm_rx(&hci_uart_h4sm, &data, 1); - return 0; -} -``` - -可以看到每接收一个字符,都使用 `hci_h4_sm_rx` 进行接收。该函数声明在 `transport\common\hci_h4\include\nimble\transport\hci_h4.h` 文件下,是关于 H4 的一个函数,大概看一下具体定义,接收字符后有一个组帧判断的过程。看一下 `hci_h4.h` 下比较关键的两个接口: - -```c++ -void hci_h4_sm_init(struct hci_h4_sm *h4sm, - const struct hci_h4_allocators *allocs, - hci_h4_frame_cb *frame_cb); - -int hci_h4_sm_rx(struct hci_h4_sm *h4sm, const uint8_t *buf, uint16_t len); -``` - -`hci_h4_sm_init()` 中出现了一个 `hci_h4_frame_cb *frame_cb` 参数,这是一个函数指针参数,初步猜测用于回调函数的注册。且在 - -`hci_uart.c` 代码中,也找到了 `hci_h4_sm_init()` 相关调用: - -```c++ -244: hci_h4_sm_init(&hci_uart_h4sm, &hci_h4_allocs_from_hs, hci_uart_frame_cb) -``` - -这里将 `hci_uart_frame_cb` 注册成了回调函数,源码中定义如下: - -```c++ -static int -hci_uart_frame_cb(uint8_t pkt_type, void *data) -{ - switch (pkt_type) { - case HCI_H4_CMD: - return ble_transport_to_ll_cmd(data); - case HCI_H4_ACL: - return ble_transport_to_ll_acl(data); - default: - assert(0); - break; - } - return -1; -} -``` - -`hci_uart_frame_cb` 基本上是对一个完整的 HCI 包的处理,根据不同的类型使用 `ble_transport_to_ll_cmd` 和 `ble_transport_to_ll_acl` 传输给 Link Layer 层( Link Layer 是 Controller 上的一个层次,更加确定这是 Controller 上的 HCI 层实现 )。 - -结合 `hci_uart.c` 中对 `hci_h4_sm` 的使用,以及对 `hci_h4_sm` 相关接口源码的分析,`hci_h4_sm` 其实是官方提供的一个类似保证包完整性的东西,用于判断一帧完整的 HCI 数据包,并且提供组包完成回调函数的机制。 - -看到这里,大概脉络应该已经捋清楚了。这是一个 Controller 上的 UART HCI 层对接实现: - -1. 向 Host 发送 HCI 包:主要通过显式实现 `ble_transport_to_hs_evt_impl` 以及 `ble_transport_to_hs_acl_impl` 接口实现,具体何时被调用,协议栈已经自动处理好。 -2. 从 Host 接收 HCI 包:主要是使用的 hci_h4 中的组包接口,hci_h4_sm 即一个组包的状态机实例,通过 `hci_h4_sm_rx` 接收 uart 接收到的字符,在判断 hci 包完整接收时调用提前注册好的 回调函数 `hci_h4_frame_cb` 。 `hci_h4_frame_cb` 里则实现了将 uart 接收到的包传递给 LL 层,进而 Controller 可以对 Host 传下来的命令或数据做出响应动作。 - - - -## 完整的 HCI 层实现 - -### Controller 使用 UART 做 HCI 层数据传输 - -开始说到无论在什么情况下都要完成 HCI 层中 4个主要接口的实现,当前 `hci_uart.c` 中只找到了两个接口的实现,还有另外两个接口在哪呢。使用全局搜索在 `nimble\controller\src\ble_ll.c` 下找到了另外两个接口的实现: - -```c++ -/* Transport APIs for LL side */ - -int -ble_transport_to_ll_cmd_impl(void *buf) -{ - return ble_ll_hci_cmd_rx(buf, NULL); -} - -int -ble_transport_to_ll_acl_impl(struct os_mbuf *om) -{ - return ble_ll_hci_acl_rx(om, NULL); -} -``` - -因为目前默认在 Controller 端实现 HCI 层,剩下未实现的两个接口在 Controller 源码下实现了。 - - - -### Host 使用 UART 做 HCI 层数据传输 - -那么假设当前需要实现 Host 端的 HCI 层,且还是需要使用 UART 对接。那么需要实现对接 UART 的接口应该刚好和 `hci_uart.c` 中相反。 - -需要在对接源码中,实现 `ble_transport_to_ll_cmd_impl` 和 `ble_transport_to_ll_acl_impl` 发送接口,具体同样也是使用 UART 发送包。相应的,在 `nimble\host\src\ble_hs.c` 下找到了以下两个接口的实现: - -```c++ -/* Transport APIs for HS side */ - -int -ble_transport_to_hs_evt_impl(void *buf) -{ - return ble_hs_hci_rx_evt(buf, NULL); -} - -int -ble_transport_to_hs_acl_impl(struct os_mbuf *om) -{ - return ble_hs_rx_data(om, NULL); -} -``` - -也就实现了 Host端 HCI 层的完整搭建。 - - - -- 在使用 UART 对接 HCI 层时,是默认当前环境只跑了 Host 或 Controller 中的一端,因此 `nimble\controller\src\ble_ll.c` 和 - - `nimble\host\src\ble_hs.c` 不会同时参与编译,自然也不会引起一些 `*impl()` 接口重复定义的错误。 - - - -### 不需要其他接口进行 HCI 传输 - -当 Host 与 Controller 跑在同一环境中,不需要对接具体的数据传输接口, `nimble\controller\src\ble_ll.c` 和 - - `nimble\host\src\ble_hs.c` 同时参与编译,此时无需再编写额外的代码,即可完整实现整个 HCI 层。 - - - -## 总结 - -在较早的版本中,NimBLE 对接 HCI 层需要实现以下接口([参考文档](https://github.com/Jackistang/HM/blob/rtthread/docs/HCI_Tramsport.md)): - -```c++ -int ble_hci_trans_hs_cmd_tx(uint8_t *cmd); -int ble_hci_trans_hs_acl_tx(struct os_mbuf *om); -void ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *cmd_cb, - void *cmd_arg, - ble_hci_trans_rx_acl_fn *acl_cb, - void *acl_arg); - -uint8_t *ble_hci_trans_buf_alloc(int type); -void ble_hci_trans_buf_free(uint8_t *buf); -int ble_hci_trans_set_acl_free_cb(os_mempool_put_fn *cb, void *arg); - -int ble_hci_trans_reset(void); -``` - -可以看出来有一些麻烦,除了处理数据传输方向,还有处理数据包的内存申请与释放,实现起来较为复杂。 - -当前版本中官方对 HCI 层进行了重构,在 `transport.c` 中统一处理了数据包的内存申请与释放;让开发者专注于处理数据的发送与接收方式,并且提供了 H4 类型的 HCI 包接收工具,更加方便开发者的对接使用。 - -- Gitee From 0575318559f45717fd4f48758f11c119057a0a45 Mon Sep 17 00:00:00 2001 From: Lenoyan <642842715@qq.com> Date: Mon, 11 Jul 2022 13:58:47 +0000 Subject: [PATCH 05/14] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20NimBLE=20HCI=20?= =?UTF-8?q?=E5=88=86=E6=9E=90=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...I \345\261\202\345\210\206\346\236\220.md" | 261 ++++++++++++++++++ 1 file changed, 261 insertions(+) create mode 100644 "rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/NimBLE HCI \345\261\202\345\210\206\346\236\220.md" diff --git "a/rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/NimBLE HCI \345\261\202\345\210\206\346\236\220.md" "b/rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/NimBLE HCI \345\261\202\345\210\206\346\236\220.md" new file mode 100644 index 0000000..c911c1a --- /dev/null +++ "b/rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/NimBLE HCI \345\261\202\345\210\206\346\236\220.md" @@ -0,0 +1,261 @@ +# NimBLE HCI 层分析 + +本文主要分析了 [Apache NimBLE](https://github.com/apache/mynewt-nimble) v1.5 版本的 BLE HCI 层设计,并分析了官方仓库自带 UART 对接例程;关于 BLE 层次结构可以先看一下这篇[参考文档](https://supperthomas-wiki.readthedocs.io/en/latest/ble/00_ble_introduce/BLE_introduce.html#id2)。 + +## NimBLE 目录结构 + +``` +NimBLE + ├───apps /* Bluetooth 示例应用程序 */ + ├───docs /* 官方文档及 API 说明 */ + ├───ext + ├───nimble + │ ├───controller /* Controller 实现 */ + │ ├───doc /* 当前包含 transport 层说明文档 */ + │ ├───drivers /* Nordic 系列 Phy 驱动 */ + │ ├───host /* Host Stack(主机控制器)实现 */ + │ ├───include + │ ├───src + │ └───transport /* HCI 传输抽象层 */ + └───porting /* OS 抽象层及系统配置 */ +``` + +- 观察目录,可以看出 NimBLE 是实现了 Host 与 Controller 分离的,在[官方介绍](https://github.com/apache/mynewt-nimble)中也有说明。 +- nimble 的 Host 可以跑在任一芯片上;Controller 则限制比较多,需要有特殊的硬件以及驱动支持。 +- `nimble/controller` 则是 Controller 相关代码; `nimble/host` 对应 Host 代码; `nimble/transport` 就是 HCI 层代码;这一版本 `nimble/doc` 下还包含了 HCI 层的说明文档 `transport.md`。 +- 顺带一提,porting 目录下是 OS 抽象层及系统配置; rt-thread 的移植就实现在 `porting/npl` 下。 + +## NimBLE HCI 层 + +> 主机控制接口层(Host Controller Interface,简写 HCI):HCI是可选的,主要用于2颗芯片实现BLE协议栈的场合(一个当作 Host 一个当作 Controller),用来规范两者之间的通信协议和通信命令等。 + +NimBLE HCI 层主要是了解 `nimble/transport` 下的内容。首先看一下官方文档 `nimble/doc/transport.md` 中对 transport 层的说明,主要看下面这张图: + +![hci_interface](figures/hci_interface.png) + +HCI 层包括这4接口:Host 从 Controller 端接收接口 `ble_transport_to_hs_evt` 和 `ble_transport_to_hs_acl`;以及 Host 向 Controller 发送接口 `ble_transport_to_ll_cmd` 和 `ble_transport_to_ll_acl`。 + +在目录下,官方流出的接口定义主要包含在下面几个文件中: + +``` +transport + └───inlucde + ├───nimble + │ └───transport + │ └───monitor.h + ├───transport_impl.h + └───transport.h +``` + +其中比较重要的是 `transport_impl.h` 文件,从名字也可以看出这是一个需要实现的接口定义文件,其主要内容如下: + +```c++ +/* Init functions to be implemented for transport acting as HS/LL side */ +extern void ble_transport_ll_init(void); +extern void ble_transport_hs_init(void); + +/* APIs to be implemented by HS/LL side of transports */ +extern int ble_transport_to_ll_cmd_impl(void *buf); +extern int ble_transport_to_ll_acl_impl(struct os_mbuf *om); +extern int ble_transport_to_hs_evt_impl(void *buf); +extern int ble_transport_to_hs_acl_impl(struct os_mbuf *om); +``` + +这些接口在 `transport\include\nimble\transport\monitor.h` 中被引用: + +```c++ +static inline int +ble_transport_to_ll_cmd(void *buf) +{ + return ble_transport_to_ll_cmd_impl(buf); +} + +static inline int +ble_transport_to_ll_acl(struct os_mbuf *om) +{ + return ble_transport_to_ll_acl_impl(om); +} + +static inline int +ble_transport_to_hs_evt(void *buf) +{ + return ble_transport_to_hs_evt_impl(buf); +} + +static inline int +ble_transport_to_hs_acl(struct os_mbuf *om) +{ + return ble_transport_to_hs_acl_impl(om); +} +``` + +看完这个文件,大概明白了,之前官方文档图中提到的 HCI 4个接口,在这里与对应的 *_impl() 接口绑定了起来。而 *impl() 接口就是官方提供给开发者具体实现对接的接口。 + +由于 Host 和 Contoller 是双向交互的,所以发送与接收 HCI 包接口是要完整实现的,也就是大多数情况下上述 4 个 *impl() 接口都需要全部实现。 + + + +## 分析 UART 对接 HCI 层官方例程 + +官方提供了一个使用 UART 对接 HCI 层的例程,源码文件为 `nimble/transport/uart/src/hci_uart.c` + +首先找到熟悉的接口:代码中显式实现了 `ble_transport_to_hs_evt_impl` 以及 `ble_transport_to_hs_acl_impl` ,这两个接口中基本上就是使用 uart 向 host 发送数据包,涉及到某个板子 uart 发送数据的具体细节,这里不过多关注。 + +看完上面两个接口,其实 HCI 中向 Host 发送数据包功能算实现完了,且当前文件中没有实现其他的 impl 接口,很容易能想到,这是写的 Controller 端的 HCI 层代码。 + +有了这个定性信息,可以开始分析如何从 uart 中接收 Host 层发来的数据包。 + +通过 uart 初始化函数找到 uart 接收回调函数: + +```c++ +// uart 初始化函数 +rc = hal_uart_init_cbs(MYNEWT_VAL(BLE_TRANSPORT_UART_PORT), + hci_uart_tx_char, NULL, + hci_uart_rx_char, NULL); +``` +```c++ +// uart 接收回调函数 +static int hci_uart_rx_char(void *arg, uint8_t data) +{ + hci_h4_sm_rx(&hci_uart_h4sm, &data, 1); + return 0; +} +``` + +可以看到每接收一个字符,都使用 `hci_h4_sm_rx` 进行接收。该函数声明在 `transport\common\hci_h4\include\nimble\transport\hci_h4.h` 文件下,是关于 H4 的一个函数,大概看一下具体定义,接收字符后有一个组帧判断的过程。看一下 `hci_h4.h` 下比较关键的两个接口: + +```c++ +void hci_h4_sm_init(struct hci_h4_sm *h4sm, + const struct hci_h4_allocators *allocs, + hci_h4_frame_cb *frame_cb); + +int hci_h4_sm_rx(struct hci_h4_sm *h4sm, const uint8_t *buf, uint16_t len); +``` + +`hci_h4_sm_init()` 中出现了一个 `hci_h4_frame_cb *frame_cb` 参数,这是一个函数指针参数,初步猜测用于回调函数的注册。且在 + +`hci_uart.c` 代码中,也找到了 `hci_h4_sm_init()` 相关调用: + +```c++ +244: hci_h4_sm_init(&hci_uart_h4sm, &hci_h4_allocs_from_hs, hci_uart_frame_cb) +``` + +这里将 `hci_uart_frame_cb` 注册成了回调函数,源码中定义如下: + +```c++ +static int +hci_uart_frame_cb(uint8_t pkt_type, void *data) +{ + switch (pkt_type) { + case HCI_H4_CMD: + return ble_transport_to_ll_cmd(data); + case HCI_H4_ACL: + return ble_transport_to_ll_acl(data); + default: + assert(0); + break; + } + return -1; +} +``` + +`hci_uart_frame_cb` 基本上是对一个完整的 HCI 包的处理,根据不同的类型使用 `ble_transport_to_ll_cmd` 和 `ble_transport_to_ll_acl` 传输给 Link Layer 层( Link Layer 是 Controller 上的一个层次,更加确定这是 Controller 上的 HCI 层实现 )。 + +结合 `hci_uart.c` 中对 `hci_h4_sm` 的使用,以及对 `hci_h4_sm` 相关接口源码的分析,`hci_h4_sm` 其实是官方提供的一个类似保证包完整性的东西,用于判断一帧完整的 HCI 数据包,并且提供组包完成回调函数的机制。 + +看到这里,大概脉络应该已经捋清楚了。这是一个 Controller 上的 UART HCI 层对接实现: + +1. 向 Host 发送 HCI 包:主要通过显式实现 `ble_transport_to_hs_evt_impl` 以及 `ble_transport_to_hs_acl_impl` 接口实现,具体何时被调用,协议栈已经自动处理好。 +2. 从 Host 接收 HCI 包:主要是使用的 hci_h4 中的组包接口,hci_h4_sm 即一个组包的状态机实例,通过 `hci_h4_sm_rx` 接收 uart 接收到的字符,在判断 hci 包完整接收时调用提前注册好的 回调函数 `hci_h4_frame_cb` 。 `hci_h4_frame_cb` 里则实现了将 uart 接收到的包传递给 LL 层,进而 Controller 可以对 Host 传下来的命令或数据做出响应动作。 + + + +## 完整的 HCI 层实现 + +### Controller 使用 UART 做 HCI 层数据传输 + +开始说到无论在什么情况下都要完成 HCI 层中 4个主要接口的实现,当前 `hci_uart.c` 中只找到了两个接口的实现,还有另外两个接口在哪呢。使用全局搜索在 `nimble\controller\src\ble_ll.c` 下找到了另外两个接口的实现: + +```c++ +/* Transport APIs for LL side */ + +int +ble_transport_to_ll_cmd_impl(void *buf) +{ + return ble_ll_hci_cmd_rx(buf, NULL); +} + +int +ble_transport_to_ll_acl_impl(struct os_mbuf *om) +{ + return ble_ll_hci_acl_rx(om, NULL); +} +``` + +因为目前默认在 Controller 端实现 HCI 层,剩下未实现的两个接口在 Controller 源码下实现了。 + + + +### Host 使用 UART 做 HCI 层数据传输 + +那么假设当前需要实现 Host 端的 HCI 层,且还是需要使用 UART 对接。那么需要实现对接 UART 的接口应该刚好和 `hci_uart.c` 中相反。 + +需要在对接源码中,实现 `ble_transport_to_ll_cmd_impl` 和 `ble_transport_to_ll_acl_impl` 发送接口,具体同样也是使用 UART 发送包。相应的,在 `nimble\host\src\ble_hs.c` 下找到了以下两个接口的实现: + +```c++ +/* Transport APIs for HS side */ + +int +ble_transport_to_hs_evt_impl(void *buf) +{ + return ble_hs_hci_rx_evt(buf, NULL); +} + +int +ble_transport_to_hs_acl_impl(struct os_mbuf *om) +{ + return ble_hs_rx_data(om, NULL); +} +``` + +也就实现了 Host端 HCI 层的完整搭建。 + + + +- 在使用 UART 对接 HCI 层时,是默认当前环境只跑了 Host 或 Controller 中的一端,因此 `nimble\controller\src\ble_ll.c` 和 + + `nimble\host\src\ble_hs.c` 不会同时参与编译,自然也不会引起一些 `*impl()` 接口重复定义的错误。 + + + +### 不需要其他接口进行 HCI 传输 + +当 Host 与 Controller 跑在同一环境中,不需要对接具体的数据传输接口, `nimble\controller\src\ble_ll.c` 和 + + `nimble\host\src\ble_hs.c` 同时参与编译,此时无需再编写额外的代码,即可完整实现整个 HCI 层。 + + + +## 总结 + +在较早的版本中,NimBLE 对接 HCI 层需要实现以下接口([参考文档](https://github.com/Jackistang/HM/blob/rtthread/docs/HCI_Tramsport.md)): + +```c++ +int ble_hci_trans_hs_cmd_tx(uint8_t *cmd); +int ble_hci_trans_hs_acl_tx(struct os_mbuf *om); +void ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *cmd_cb, + void *cmd_arg, + ble_hci_trans_rx_acl_fn *acl_cb, + void *acl_arg); + +uint8_t *ble_hci_trans_buf_alloc(int type); +void ble_hci_trans_buf_free(uint8_t *buf); +int ble_hci_trans_set_acl_free_cb(os_mempool_put_fn *cb, void *arg); + +int ble_hci_trans_reset(void); +``` + +可以看出来有一些麻烦,除了处理数据传输方向,还有处理数据包的内存申请与释放,实现起来较为复杂。 + +当前版本中官方对 HCI 层进行了重构,在 `transport.c` 中统一处理了数据包的内存申请与释放;让开发者专注于处理数据的发送与接收方式,并且提供了 H4 类型的 HCI 包接收工具,更加方便开发者的对接使用。 + -- Gitee From 0ff2956c9f5fbd76e9429e70d8547799a08415ca Mon Sep 17 00:00:00 2001 From: Lenoyan <642842715@qq.com> Date: Mon, 11 Jul 2022 13:59:09 +0000 Subject: [PATCH 06/14] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20NimBLE=20HCI=20?= =?UTF-8?q?=E5=88=86=E6=9E=90=E6=96=87=E6=A1=A3=20=E5=9B=BE=E7=89=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nimble-docs/figures/hci_interface.png | Bin 0 -> 11280 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/figures/hci_interface.png diff --git a/rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/figures/hci_interface.png b/rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/figures/hci_interface.png new file mode 100644 index 0000000000000000000000000000000000000000..1161b72e24b73d2fad253fff03b84eadb42f0a6c GIT binary patch literal 11280 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 Date: Mon, 11 Jul 2022 13:59:31 +0000 Subject: [PATCH 07/14] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20rt?= =?UTF-8?q?-thread-version/rt-thread-standard/packages-manual/nimble-docs/?= =?UTF-8?q?.keep?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rt-thread-standard/packages-manual/nimble-docs/.keep | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/.keep diff --git a/rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/.keep b/rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/.keep deleted file mode 100644 index e69de29..0000000 -- Gitee From b00c11b5cd76074360a9432f5c76198273af6cb9 Mon Sep 17 00:00:00 2001 From: Lenoyan <642842715@qq.com> Date: Mon, 11 Jul 2022 13:59:37 +0000 Subject: [PATCH 08/14] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20rt?= =?UTF-8?q?-thread-version/rt-thread-standard/packages-manual/nimble-docs/?= =?UTF-8?q?figures/.keep?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rt-thread-standard/packages-manual/nimble-docs/figures/.keep | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/figures/.keep diff --git a/rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/figures/.keep b/rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/figures/.keep deleted file mode 100644 index e69de29..0000000 -- Gitee From 4aec07265ac426bff84b66b03bbc20f6565a5b92 Mon Sep 17 00:00:00 2001 From: Lenoyan <642842715@qq.com> Date: Mon, 11 Jul 2022 14:00:40 +0000 Subject: [PATCH 09/14] =?UTF-8?q?=E9=87=8D=E5=91=BD=E5=90=8D=20rt-thread-v?= =?UTF-8?q?ersion/rt-thread-standard/packages-manual/nimble-docs/NimBLE=20?= =?UTF-8?q?HCI=20=E5=B1=82=E5=88=86=E6=9E=90.md=20=E4=B8=BA=20rt-thread-ve?= =?UTF-8?q?rsion/rt-thread-standard/packages-manual/nimble-docs/NimBLE=20H?= =?UTF-8?q?CI=20Transport=20Layer=20Analysis.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nimble-docs/NimBLE HCI Transport Layer Analysis.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename "rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/NimBLE HCI \345\261\202\345\210\206\346\236\220.md" => rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/NimBLE HCI Transport Layer Analysis.md (100%) diff --git "a/rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/NimBLE HCI \345\261\202\345\210\206\346\236\220.md" b/rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/NimBLE HCI Transport Layer Analysis.md similarity index 100% rename from "rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/NimBLE HCI \345\261\202\345\210\206\346\236\220.md" rename to rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/NimBLE HCI Transport Layer Analysis.md -- Gitee From 98aba6fe6d3422a74c6ee0cfd927667c8cac44b4 Mon Sep 17 00:00:00 2001 From: Lenoyan <642842715@qq.com> Date: Mon, 11 Jul 2022 14:20:02 +0000 Subject: [PATCH 10/14] =?UTF-8?q?update=20rt-thread-version/rt-thread-stan?= =?UTF-8?q?dard/=5Fsidebar.md.=20=E8=BD=AF=E4=BB=B6=E5=8C=85-=E7=89=A9?= =?UTF-8?q?=E8=81=94=E7=BD=91=20=E7=9B=AE=E5=BD=95=E4=B8=8B=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=20NimBLE=20=E7=9B=AE=E5=BD=95=EF=BC=8C=E5=B9=B6?= =?UTF-8?q?=E4=B8=94=E6=B7=BB=E5=8A=A0=20NimBLE=20HCI=20=E5=88=86=E6=9E=90?= =?UTF-8?q?=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- rt-thread-version/rt-thread-standard/_sidebar.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rt-thread-version/rt-thread-standard/_sidebar.md b/rt-thread-version/rt-thread-standard/_sidebar.md index ac6b499..156f19b 100644 --- a/rt-thread-version/rt-thread-standard/_sidebar.md +++ b/rt-thread-version/rt-thread-standard/_sidebar.md @@ -92,6 +92,8 @@ - [rw007 SPI WiFi 模块使用](/rt-thread-version/rt-thread-standard/application-note/packages/rw007_module_using/an0034-rw007-module-using.md) - [MQTT-umqtt](/rt-thread-version/rt-thread-standard/application-note/packages/umqtt/umqtt.md) - [Telent](/rt-thread-version/rt-thread-standard/application-note/packages/netutils/telent.md) + - NimBLE + - [NimBLE HCI层分析](/rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/NimBLE_HCI_Transport_Layer_Analysis.md) - 工具 - [SystemView 分析工具](/rt-thread-version/rt-thread-standard/application-note/debug/systemview/an0009-systemview.md) - [Segger RTT](/rt-thread-version/rt-thread-standard/application-note/debug/seggerRTT/segger_rtt.md) -- Gitee From 2a53c126ba3a8e003bff559157f253cf6b71251e Mon Sep 17 00:00:00 2001 From: Lenoyan <642842715@qq.com> Date: Mon, 11 Jul 2022 14:20:53 +0000 Subject: [PATCH 11/14] =?UTF-8?q?=E9=87=8D=E5=91=BD=E5=90=8D=20rt-thread-v?= =?UTF-8?q?ersion/rt-thread-standard/packages-manual/nimble-docs/NimBLE=20?= =?UTF-8?q?HCI=20Transport=20Layer=20Analysis.md=20=E4=B8=BA=20rt-thread-v?= =?UTF-8?q?ersion/rt-thread-standard/packages-manual/nimble-docs/NimBLE=5F?= =?UTF-8?q?HCI=5FTransport=5FLayer=5FAnalysis.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...t Layer Analysis.md => NimBLE_HCI_Transport_Layer_Analysis.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/{NimBLE HCI Transport Layer Analysis.md => NimBLE_HCI_Transport_Layer_Analysis.md} (100%) diff --git a/rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/NimBLE HCI Transport Layer Analysis.md b/rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/NimBLE_HCI_Transport_Layer_Analysis.md similarity index 100% rename from rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/NimBLE HCI Transport Layer Analysis.md rename to rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/NimBLE_HCI_Transport_Layer_Analysis.md -- Gitee From 266a87843fee72e31f94e896ae74f6c0a988b5e0 Mon Sep 17 00:00:00 2001 From: Lenoyan <642842715@qq.com> Date: Tue, 12 Jul 2022 03:07:26 +0000 Subject: [PATCH 12/14] =?UTF-8?q?update=20rt-thread-version/rt-thread-stan?= =?UTF-8?q?dard/=5Fsidebar.md.=20=E4=BF=AE=E6=94=B9=20NimBLE=20=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E7=BC=A9=E8=BF=9B=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- rt-thread-version/rt-thread-standard/_sidebar.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rt-thread-version/rt-thread-standard/_sidebar.md b/rt-thread-version/rt-thread-standard/_sidebar.md index 156f19b..4fbcc46 100644 --- a/rt-thread-version/rt-thread-standard/_sidebar.md +++ b/rt-thread-version/rt-thread-standard/_sidebar.md @@ -93,7 +93,7 @@ - [MQTT-umqtt](/rt-thread-version/rt-thread-standard/application-note/packages/umqtt/umqtt.md) - [Telent](/rt-thread-version/rt-thread-standard/application-note/packages/netutils/telent.md) - NimBLE - - [NimBLE HCI层分析](/rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/NimBLE_HCI_Transport_Layer_Analysis.md) + - [NimBLE HCI层分析](/rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/NimBLE_HCI_Transport_Layer_Analysis.md) - 工具 - [SystemView 分析工具](/rt-thread-version/rt-thread-standard/application-note/debug/systemview/an0009-systemview.md) - [Segger RTT](/rt-thread-version/rt-thread-standard/application-note/debug/seggerRTT/segger_rtt.md) -- Gitee From 11fba6ebb0c6111cc4107f913273c23573a2e375 Mon Sep 17 00:00:00 2001 From: Lenoyan <642842715@qq.com> Date: Tue, 12 Jul 2022 14:09:44 +0000 Subject: [PATCH 13/14] =?UTF-8?q?update=20rt-thread-version/rt-thread-stan?= =?UTF-8?q?dard/=5Fsidebar.md.=20=E8=B0=83=E6=95=B4=20nimble=20=E7=9B=AE?= =?UTF-8?q?=E5=BD=95=E4=BD=8D=E7=BD=AE=EF=BC=8C=E8=BD=AF=E4=BB=B6=E5=8C=85?= =?UTF-8?q?=20-=20NimBLE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- rt-thread-version/rt-thread-standard/_sidebar.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rt-thread-version/rt-thread-standard/_sidebar.md b/rt-thread-version/rt-thread-standard/_sidebar.md index 4fbcc46..43cf3db 100644 --- a/rt-thread-version/rt-thread-standard/_sidebar.md +++ b/rt-thread-version/rt-thread-standard/_sidebar.md @@ -92,8 +92,6 @@ - [rw007 SPI WiFi 模块使用](/rt-thread-version/rt-thread-standard/application-note/packages/rw007_module_using/an0034-rw007-module-using.md) - [MQTT-umqtt](/rt-thread-version/rt-thread-standard/application-note/packages/umqtt/umqtt.md) - [Telent](/rt-thread-version/rt-thread-standard/application-note/packages/netutils/telent.md) - - NimBLE - - [NimBLE HCI层分析](/rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/NimBLE_HCI_Transport_Layer_Analysis.md) - 工具 - [SystemView 分析工具](/rt-thread-version/rt-thread-standard/application-note/debug/systemview/an0009-systemview.md) - [Segger RTT](/rt-thread-version/rt-thread-standard/application-note/debug/seggerRTT/segger_rtt.md) @@ -113,6 +111,8 @@ - TinyUSB 用户手册 - [介绍](/rt-thread-version/rt-thread-standard/packages-manual/tinyusb-docs/introduction.md) - [USB 设备](/rt-thread-version/rt-thread-standard/packages-manual/tinyusb-docs/device.md) + - NimBLE + - [NimBLE HCI层分析](/rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/NimBLE_HCI_Transport_Layer_Analysis.md) - [更多软件包...](/rt-thread-version/rt-thread-standard/packages-manual/more.md) - 应用开发 - 开发环境搭建 -- Gitee From 49cffd6dab73961602538611eac1a00f1e727b2a Mon Sep 17 00:00:00 2001 From: Lenoyan <642842715@qq.com> Date: Tue, 12 Jul 2022 14:13:27 +0000 Subject: [PATCH 14/14] update rt-thread-version/rt-thread-standard/_sidebar.md. --- rt-thread-version/rt-thread-standard/_sidebar.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rt-thread-version/rt-thread-standard/_sidebar.md b/rt-thread-version/rt-thread-standard/_sidebar.md index 43cf3db..b63c645 100644 --- a/rt-thread-version/rt-thread-standard/_sidebar.md +++ b/rt-thread-version/rt-thread-standard/_sidebar.md @@ -111,7 +111,7 @@ - TinyUSB 用户手册 - [介绍](/rt-thread-version/rt-thread-standard/packages-manual/tinyusb-docs/introduction.md) - [USB 设备](/rt-thread-version/rt-thread-standard/packages-manual/tinyusb-docs/device.md) - - NimBLE + - NimBLE 用户手册 - [NimBLE HCI层分析](/rt-thread-version/rt-thread-standard/packages-manual/nimble-docs/NimBLE_HCI_Transport_Layer_Analysis.md) - [更多软件包...](/rt-thread-version/rt-thread-standard/packages-manual/more.md) - 应用开发 -- Gitee