使用 B91 开发板和 OpenThread 构建 Thread 网络

1. 简介

26b7f4f6b3ea0700

OpenThreadThread® 网络协议的开源实现,后者是专为物联网 (IoT) 设备设计的强大且安全的无线网状网络协议。OpenThread 由 Google 的 Nest 团队开发,作为开源项目免费提供给开发者社区。

Thread 规范为智能家居和商业建筑中常见的资源受限的设备制定了可靠、安全且节能的无线通信协议。OpenThread 在 Thread 中包含完整的网络层范围,例如具有 MAC 安全、网状链路建立和网格路由的 IPv6、6LoWPAN、IEEE 802.15.4。

Telink 已将 OpenThread 实现集成到 Zephyr RTOS 中,以实现与 Telink 硬件的无缝兼容性。您可以在 GitHub 上轻松获取这项集成的源代码,也可以使用软件开发套件 (SDK) 的形式获得这些代码。

在此 Codelab 中,您将在实际硬件上对 OpenThread 进行编程,创建和管理 Thread 网络,并在节点之间交换消息。下图描绘了硬件设置,其中包含一个 OT 边界路由器 (OTBR) 和一个 Codelab 设备。

codelab_overview.png

学习内容

  • 使用 Telink Zephyr 开发环境设置 OpenThread 实现。
  • 构建 OpenThread CLI 示例(ot-cli-ftdot-rcp),并将其刷入 Telink B91 Development Boards。
  • 在 Raspberry Pi 3B 及更高版本上使用 Docker 设置 OpenThread 边界路由器 (OTBR)。
  • 在 OTBR 上创建 Thread 网络。
  • 使用带外调试功能将设备添加到 Thread 网络。
  • 使用 CLI 验证 Thread 网络中节点之间的连接。

所需条件

硬件:

  • 两个 B91 开发板。
  • 一个搭载 Raspbian 操作系统映像的 Raspberry Pi 3B 或更高版本。
  • 具有至少两个 USB 端口的 Linux 机器。
  • 一个连接到互联网的交换机(或路由器)和多条以太网网线。

软件:

  • Telink 刻录和调试工具 —— LinuxBDT。
  • 串行端口终端工具,例如 PuTTY。
  • 其他工具,例如 Git 和 West。

2. 前提条件

Thread 概念和 OpenThread CLI

在学习此 Codelab 之前,最好先浏览 OpenThread 模拟 Codelab,熟悉 Thread 的基本概念和 OpenThread CLI。

Linux 机器

Linux 机器(Ubuntu v20.04 LTS 或更高版本)充当构建机器,用于设置 Telink Zephyr 开发环境并刷写所有 Thread 开发板。要完成这些任务,Linux 机器需要两个可用的 USB 端口和互联网连接。

串行端口连接和终端

您可以将设备直接插入 Linux 计算机的 USB 端口。此外,您还需要使用串行端口终端工具来访问设备。

在此 Codelab 中,终端工具 PuTTY 用于控制 FTD 连接器和 Raspberry Pi。它提供了其用法概览,但也可以使用其他终端软件。

此 Codelab 需要两套 B91 开发套件。下图显示了一组所需的最少量组件。

overview.png

其中一个套件将用作 RCP(无线电协同处理器),另一个将用作 FTD(全线程设备)。如果您尚未收到该套件,可以访问 Telink 官方网站获取更多详细信息。需要使用的一些组件如下:

索引

名称

1

Telink B91 开发板

2

Telink 燃烧板

3

2.4Ghz 天线

4

USB 线(USB A 转迷你 USB)

搭载 Raspbian 操作系统映像的 Raspberry Pi 3B 或更高版本

在此 Codelab 中,需要搭载 Raspbian Bullseye Lite OS 映像Raspbian Bullseye with Desktop 的 Raspberry Pi 3B 或更高版本。该设备通过以太网连接到互联网,并将被配置为 OpenThread 边界路由器 (OTBR) 的主机。

网络连接

一个连接到互联网的交换机(或路由器)和多条以太网网线。它们用于将 Raspberry Pi 连接到 Linux 机器,方便用户通过主机配置 Raspberry Pi。

LinuxBDT

Telink Burning and Debugging Tool (BDT) 适用于所有 Telink 芯片系列,可让您擦除 OpenThread 固件并将其刷写到 Telink B91 开发板上。在 Linux 计算机上安装基于 X86 的 Linux 版本 linuxBDT

其他

  • Git,用于设置 Telink Zephyr 开发环境。
  • West,用于管理 Zephyr 项目和构建 OpenThread 二进制文件。

3. 设置固件

在 Linux 机器上,打开 CLI 终端,首先执行以下命令,确保您的 APT 为最新版本。

$ sudo apt update
$ sudo apt upgrade

完成后,请继续执行以下步骤。

  1. 安装依赖项。
    $ wget https://apt.kitware.com/kitware-archive.sh
    $ sudo bash kitware-archive.sh
    $ sudo apt install --no-install-recommends git cmake ninja-build \
    gperf ccache dfu-util device-tree-compiler python3-dev python3-pip \
    python3-setuptools python3-tk python3-wheel xz-utils file make gcc \
    gcc-multilib g++-multilib libsdl2-dev
    
    Zephyr 目前要求使用最低版本的主依赖项,例如 CMake (3.20.0)、Python3 (3.6) 和设备树编译器 (1.4.6)。
    $ cmake --version
    $ python3 --version
    $ dtc --version
    
    在继续执行后续步骤之前,请验证系统中已安装的版本。如果版本不正确,请将 APT 镜像切换到稳定且最新的镜像,或手动更新这些依赖项。
  2. 安装 west。
    $ pip3 install --user -U west
    $ echo 'export PATH=~/.local/bin:"$PATH"' >> ~/.bashrc
    $ source ~/.bashrc
    
    确保 ~/.local/bin 位于 $PATH 环境变量中。
  3. 获取 Zephyr 项目源代码。
    $ west init ~/zephyrproject
    $ cd ~/zephyrproject
    $ west update
    $ west blobs fetch hal_telink
    $ west zephyr-export
    
  4. 为 Zephyr 安装其他 Python 依赖项。
    $ pip3 install --user -r ~/zephyrproject/zephyr/scripts/requirements.txt
    
  5. 设置 Zephyr 工具链。将 Zephyr 工具链(大约 1~2 GB)下载到本地目录,以便刷写大多数开发板。
    $ wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.1/zephyr-sdk-0.16.1_linux-x86_64.tar.xz
    $ wget -O - https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.1/sha256.sum | shasum --check --ignore-missing
    
    下载 Zephyr SDK 并将其放置在推荐的路径中,如下所示。
    $HOME/zephyr-sdk[-x.y.z]
    $HOME/.local/zephyr-sdk[-x.y.z]
    $HOME/.local/opt/zephyr-sdk[-x.y.z]
    $HOME/bin/zephyr-sdk[-x.y.z]
    /opt/zephyr-sdk[-x.y.z]
    /usr/zephyr-sdk[-x.y.z]
    /usr/local/zephyr-sdk[-x.y.z]
    
    其中 [-x.y.z] 是可选文本,可以是任何文本,例如 -0.16.1。安装 SDK 后,此目录便无法移动。然后安装 Zephyr 工具链。
    $ tar xvf zephyr-sdk-0.16.1_linux-x86_64.tar.xz
    $ cd zephyr-sdk-0.16.1
    $ ./setup.sh -t riscv64-zephyr-elf -h -c
    
  6. 构建 Hello World 示例。首先,使用 Hello World 示例验证官方 Zephyr 项目配置是否正确,然后继续设置您的自定义项目。
    $ cd ~/zephyrproject/zephyr
    $ west build -p auto -b tlsr9518adk80d samples/hello_world
    
    使用 West build 命令从 Zephyr 代码库的根目录构建 hello_world 示例。您可以在 build/zephyr directory 下找到名为 zephyr.bin 的固件。
  7. 将 Zephyr 环境脚本添加到 ~/.bashrc。执行以下命令。
    $ echo "source ~/zephyrproject/zephyr/zephyr-env.sh" >> ~/.bashrc
    $ source ~/.bashrc
    
  8. 添加 Telink Zephyr 远程代码库。在本地将 Telink 代码库下载为开发分支并进行更新。
    $ cd ~/zephyrproject/zephyr
    $ git remote add telink-semi https://github.com/telink-semi/zephyr
    $ git fetch telink develop
    $ git checkout develop
    $ west update
    $ west blobs fetch hal_telink
    

如需了解详情,请参阅 Zephyr Doc - 使用入门指南

下载 Telink LinuxBDT 工具并将其解压缩到 Linux 计算机上的本地目录(例如主目录 ~),以便将固件刷写到 B91 开发板上。

$ cd ~
$ wget http://wiki.telink-semi.cn/tools_and_sdk/Tools/BDT/LinuxBDT.tar.bz2
$ tar -vxf LinuxBDT.tar.bz2 

通过 USB 接口将 Burning Board 连接到 Linux 计算机,然后输入以下命令。

$ cd LinuxBDT
$ sudo ./bdt lsusb -v
Bus 002 Device 001: ID 1d6b:0003 xHCI Host Controller
Bus 001 Device 003: ID 0bda:565a Integrated_Webcam_HD
Bus 001 Device 023: ID 413c:301a Dell MS116 USB Optical Mouse
Bus 001 Device 037: ID 248a:826a Telink Web Debugger v3.6
Bus 001 Device 001: ID 1d6b:0002 xHCI Host Controller

如果您看到“Telink Web Debugger v3.6”的消息,则表示 BDT 程序员已成功连接到 Linux 计算机。

固件编译

此 Codelab 将构建两种类型的 OpenThread 固件:

  • ot-cli-ftd
  • ot-rcp

编译方法如下所示:

  1. 无线装置协同处理器 (ot-rcp)
    $ cd ~/zephyrproject
    $ rm -rf build_ot_coprocessor
    $ west build -b tlsr9518adk80d -d build_ot_coprocessor zephyr/samples/net/openthread/coprocessor -- -DDTC_OVERLAY_FILE="usb.overlay" -DOVERLAY_CONFIG=overlay-rcp-usb-telink.conf
    
  2. 具有交互式命令行的全功能线程设备 (ot-cli-ftd)
    $ cd ~/zephyrproject
    $ rm -rf build_ot_cli_ftd
    $ west build -b tlsr9518adk80d -d build_ot_cli_ftd zephyr/samples/net/openthread/cli -- -DOVERLAY_CONFIG=overlay-telink-fixed-mac.conf -DCONFIG_OPENTHREAD_FTD=y
    

固件闪存

使用 USB 线将 B91 开发板连接到 Burning Board,如下图所示。

connection_overview.png

在命令行中,执行以下命令以执行固件刻录(以 ot-cli-ftd 固件刷写为例)。

$ cd ~/zephyrproject/build_ot_cli_ftd/zephyr
$ cp zephyr.bin ~/LinuxBDT/bin/ot-cli-ftd.bin
$ cd ~/LinuxBDT
$ sudo ./bdt 9518 ac
 Activate OK!
$ sudo ./bdt 9518 wf 0 -i bin/ot-cli-ftd.bin
 EraseSectorsize...
 Total Time: 2181 ms
 Flash writing...
 [100%][-] [##################################################]
 File Download to Flash at address 0x000000: 491700 bytes
 Total Time: 30087 ms

ot-rcp 的刷写方法与 ot-cli-ftd 的刷写方法基本相同。不过,固件路径和名称有所不同。

刷写后,通过进行相应标记将两个 B91 开发板区分开来。将刷写了 ot-cli-ftd 的开发板标记为“FTD 连接器”开发板上闪烁显示 ot-rcp 为“RCP”。

4. 为 FTD 连接器设备配置串行控制台

如图所示,将 FTD 连接器直接插入 Linux 计算机的 USB 端口。

usb_connection.png

将 FTD 连接器设备连接到 Linux 计算机后,打开 PuTTY。然后创建一个新终端,设置串行端口信息,并打开串行端口。

uart_console.png

OpenThread 命令行参考位于:OpenThread CLI Reference。请务必为所有命令添加 ot 前缀。

示例:

> ot state
disabled
Done
> ot channel
11
Done
>

5. 将 Raspberry Pi 设置为 OpenThread 边界路由器

OpenThread 边界路由器是一种设备,由两个主要部分组成:

  • Raspberry Pi 包含充当边界路由器 (BR) 所需的所有服务和固件。
  • RCP 负责线程通信。

无线电协同处理器 (RCP)

如需刷写 ot-rcp 固件,请按照与 ot-cli-ftd 固件刷写过程相同的步骤操作。将 B91 开发板连接到 Raspberry Pi 上的 USB 端口,如下图所示。

OTBR_overview.png

树莓派

  1. 确保 Raspbian Bullseye Lite 操作系统映像Raspbian Bullseye with Desktop 已正确写入 SD 卡。
  2. 您可以选择通过 SSH 连接到 Raspberry Pi 或直接使用 Raspbian 桌面。此 Codelab 将使用 SSH。
  3. 在下一步中继续安装 OTBR Docker 之前,请务必先更新本地代码库和软件包管理器。
    $ sudo apt-get update
    $ sudp apt-get upgrade
    

安装 Docker

如果您只是在上一步中更新本地代码库和软件包管理器 APT,请重新启动 Raspberry Pi,然后打开 SSH 终端窗口。

  1. 安装 Docker:
    $ curl -sSL https://get.docker.com | sh
    
  2. 将当前账号放入 Docker 群组以授予权限,这样就无需在每个命令前面添加 sudo
    $ sudo usermod -aG docker $USER
    
    您需要重启 Raspberry Pi 才能生效。
  3. 如果 Docker 尚未启动,请将其启动:
    $ sudo dockerd
    
  4. OTBR 防火墙脚本在 Docker 容器内部生成规则。在此之前,执行 modprobe 以加载 iptables 的内核模块。
    $ sudo modprobe ip6table_filter
    

配置并运行 Docker

此 Codelab 直接从 OpenThread Docker Hub 拉取 OTBR Docker 映像。此映像已经过 OpenThread 团队的测试和验证。

  1. 拉取最新的映像:
    $ docker pull openthread/otbr:latest
    
  2. 检查 Docker 容器中的映像列表:
    $ docker images
    REPOSITORY        TAG       IMAGE ID       CREATED      SIZE
    openthread/otbr   latest    db081f4de15f   6 days ago   766MB
    
  3. 通过检查 /dev 确定 RCP 设备的串行端口名称,ttyACM0 表示 RCP 已正确连接。
    $ ls /dev/tty*
    ...
    /dev/ttyACM0
    ... 
    
  4. 首次运行 OTBR Docker,并引用 RCP 的串行端口 (ttyACM0)。如果您想继续使用此 OTBR Docker,请使用命令 docker start otbr
    $ docker run --name "otbr" --sysctl "net.ipv6.conf.all.disable_ipv6=0 net.ipv4.conf.all.forwarding=1 net.ipv6.conf.all.forwarding=1" -p 8080:80 --dns=127.0.0.1 -it --volume /dev/ttyACM0:/dev/ttyACM0 --privileged openthread/otbr --radio-url spinel+hdlc+uart:///dev/ttyACM0
    
  5. 打开新的 SSH 终端窗口,以测试 Raspberry Pi 与 RCP 之间的连接。
    $ docker exec -ti otbr sh -c "sudo ot-ctl"
    > state 
    disabled
    Done
    

可选的 Docker 命令:

  • 获取有关正在运行的 Docker 容器的信息:
    $ docker ps -aq
    
  • 停止 OTBR Docker:
    $ docker stop otbr
    
  • 移除 OTBR Docker:
    $ docker rm otbr
    
  • 重新加载 OTBR Docker:
    $ docker restart otbr
    

此时,FTD 连接器设备和 OTBR 都已准备就绪,您可以继续执行下一步来构建 Thread 网络。

6. 创建 Thread 网络

在 RCP 上创建 Thread 网络

我们使用 OTBR 上的 ot-ctl shell 建立 Thread 网络。如果您在上一部分中退出了 shell,请输入以下命令,以在 SSH 终端中重新启动它:

$ docker exec -ti otbr sh -c "sudo ot-ctl"

接下来,按照表中指定的顺序输入命令,并确保每个步骤都达到预期结果,然后再继续下一个步骤。

索引

命令

简介

预期响应

1

dataset init new

创建新的随机网络数据集。

完成

2

dataset commit active

将新数据集提交到非易失性存储空间中的活跃运营数据集。

完成

3

ifconfig up

启动 IPv6 接口。

完成

4

thread start

启用 Thread 协议操作并连接到 Thread 网络。

完成

等待 10 秒钟,让线程接口启动。

5

state

检查设备状态。此命令可以多次调用,直到它成为主要副本并进入下一步。

leader
Done

6

dataset active

检查完整的活跃运营数据集并记录网络密钥。











ot-cli-ftd 台设备加入此 Thread 网络时,将使用在创建网络期间 OTBR 随机生成的网络密钥。

通过带外调试将 FTD 连接符添加到 Thread

带外调试是指通过非无线方法(例如,在 OpenThread CLI 中手动输入)将网络凭据传输到等待加入网络的设备。在串行控制台中依次输入以下命令:FTD 连接器。

索引

命令

简介

预期响应数

1

ot dataset networkkey c312485187484ceb5992d2343baaf93d

只有网络密钥是设备连接到 Thread 网络所必需的。

完成

2

ot dataset commit active

将新数据集提交到非易失性存储空间中的活跃运营数据集。

完成

3

ot ifconfig up

启动 IPv6 接口。

完成

4

ot thread start

启用 Thread 协议操作并连接到 Thread 网络。

完成

等待 20 秒,让设备加入并自行配置。

5

ot state

检查设备状态。

孩子/路由器
完成

拓扑

在 SSH 终端中输入 ipaddrchild tablerouter table 等命令,获取类似以下代码段的响应。

> ipaddr rloc
fd8c:60bc:a98:c7ba:0:ff:fe00:b000
Done
> child table
| ID  | RLOC16 | Timeout    | Age        | LQ In | C_VN |R|D|N|Ver|CSL|QMsgCnt|Suprvsn| Extended MAC     |
+-----+--------+------------+------------+-------+------+-+-+-+---+---+-------+-------+------------------+
|   1 | 0xb001 |        240 |         23 |     3 |   51 |1|1|1|  3| 0 |     0 |   129 | 82bc12fbe783468e |

Done
> router table
| ID | RLOC16 | Next Hop | Path Cost | LQ In | LQ Out | Age | Extended MAC     | Link |
+----+--------+----------+-----------+-------+--------+-----+------------------+------+
| 44 | 0xb000 |       63 |         0 |     0 |      0 |   0 | 7ae354109d611f7e |    0 |

Done
...
> child table
| ID  | RLOC16 | Timeout    | Age        | LQ In | C_VN |R|D|N|Ver|CSL|QMsgCnt|Suprvsn| Extended MAC     |
+-----+--------+------------+------------+-------+------+-+-+-+---+---+-------+-------+------------------+

Done
> router table
| ID | RLOC16 | Next Hop | Path Cost | LQ In | LQ Out | Age | Extended MAC     | Link |
+----+--------+----------+-----------+-------+--------+-----+------------------+------+
| 33 | 0x8400 |       63 |         0 |     3 |      3 |  13 | e61487c1cda940a6 |    1 |
| 44 | 0xb000 |       63 |         0 |     0 |      0 |   0 | 7ae354109d611f7e |    0 |

Done

OTBR 的 RLOC160xb000,FTD 联接器的 RLOC16 最初为 0xb001。然后,在获取路由器 ID 后,FTD 联接器的 RLOC16 会变为 0x8400。可以看到,FTD 连接符已从子级升级为路由器。

当前的 Thread 网络包含两个节点,拓扑如下图所示。

topology.png

7. 线程设备之间的通信

ICMPv6 通信

我们使用 ping 命令检查同一网络中的 Thread 设备是否可以相互通信。首先,使用 ipaddr 命令获取设备的 RLOC。

> ipaddr
fd8c:60bc:a98:c7ba:0:ff:fe00:fc11
fdbd:7274:649c:1:1d19:9613:f705:a5af
fd8c:60bc:a98:c7ba:0:ff:fe00:fc10
fd8c:60bc:a98:c7ba:0:ff:fe00:fc38
fd8c:60bc:a98:c7ba:0:ff:fe00:fc00
fd8c:60bc:a98:c7ba:0:ff:fe00:b000       # Routing Locator (RLOC)
fd8c:60bc:a98:c7ba:5249:34ab:26d1:aff6
fe80:0:0:0:78e3:5410:9d61:1f7e
Done

在 FTD 联接器的串行控制台中输入以下命令以执行 ping 操作。

> ot ping fd8c:60bc:a98:c7ba:0:ff:fe00:b000
16 bytes from fd8c:60bc:a98:c7ba:0:ff:fe00:b000: icmp_seq=1 hlim=64 time=19ms
1 packets transmitted, 1 packets received. Packet loss = 0.0%. Round-trip min/avg/max = 19/19.0/19 ms.
Done

串行端口的输出响应表明 OTBR 端已收到 ping 请求,且 FTD 联接器已收到 OTBR 返回的 ping 响应。两台设备之间的通信成功。

UDP 通信

OpenThread 提供的应用服务也包括 UDP。您可以使用 UDP API 在 Thread 网络中的节点之间传递信息,或通过边界路由器将信息传递给外部网络。如需详细了解 OpenThread 的 UDP API,请参阅 OpenThread CLI - UDP 示例。此 Codelab 将使用其中的部分 API 在 OTBR 和 FTD 联接器之间传输信息。

首先,获取 OTBR 的 Mesh-Local EID。此地址也是 Thread 设备的 IPv6 地址之一,可用于访问同一 Thread 网络分区中的 Thread 设备。

> ipaddr mleid
fd8c:60bc:a98:c7ba:5249:34ab:26d1:aff6
Done

在 SSH 终端中输入以下命令以启用 OTBR UDP 并绑定设备的 1022 端口。

> udp open
Done
> udp bind :: 1022
Done

在串行控制台中输入以下命令,并启用 FTD 联接器的 UDP。绑定设备的 1022 端口,然后向 OTBR 发送 5 字节的 hello 消息。

> ot udp open 
Done
> ot udp bind :: 1022
Done
> ot udp send fd8c:60bc:a98:c7ba:5249:34ab:26d1:aff6 1022 hello
Done

SSH 终端会输出以下信息。OTBR 收到来自 FTD 联接器的 hello 消息,表示 UDP 通信成功。

> 5 bytes from fd8c:60bc:a98:c7ba:9386:63cf:19d7:5a61 1022 hello

8. 恭喜

您创建了一个简单的 Thread 网络,并验证了此网络中的通信。

您现在已了解:

  • 如何构建和使用 Telink Zephyr 开发环境。
  • 如何构建 ot-cli-ftdot-rcp 二进制文件,以及如何将其刷写到 Telink B91 开发板上。
  • 如何使用 Docker 将 Raspberry Pi 3B 或更高版本设置为 OpenThread 边界路由器 (OTBR)。
  • 如何在 OTBR 上创建 Thread 网络。
  • 如何通过带外调试将设备添加到 Thread 网络。
  • 如何验证 Thread 网络中节点之间的连接。

延伸阅读

访问 openthread.ioGitHub,了解各种 OpenThread 资源,包括:

参考文档: