Using B91 EVB and OpenThread to Build a Thread Network
Introduction
OpenThread is an open-source implementation of the Thread networking protocol, which is a robust and secure wireless mesh networking protocol designed for the Internet of Things (IoT) devices.
OpenThread was developed by Google's Nest team and is freely available to the developer community as an open-source project.
The Thread Specification establishes a reliable, secure, and energy-efficient wireless communication protocol for resource-constrained devices commonly found in smart homes and commercial buildings.
OpenThread includes the full network layer scope within Thread, such as IPv6, 6LoWPAN, IEEE 802.15.4 with MAC security, mesh link establishment, and mesh routing.
Telink has integrated the OpenThread implementation into Zephyr RTOS, enabling seamless compatibility with Telink hardware.
The source code for this integration is readily accessible on GitHub, and it is also provided as a software development kit (SDK).
In this codelab, you will program OpenThread on actual hardware, create and manage a Thread network, and exchange messages between nodes.
The image below depicts the hardware setup, featuring an OT Border Router (OTBR) and one Thread device in the codelab.
Learning Content
-
To set up OpenThread implementation using the Telink Zephyr development environment.
-
To build the OpenThread CLI samples (
ot-cli-ftd
andot-rcp
) and flash them onto Telink B91 Development Boards. -
To set up an OpenThread Border Router (OTBR) using Docker on a Raspberry Pi 3B+ or later.
-
To create a Thread network on the OTBR.
-
To add devices to the Thread network using out-of-band debugging.
-
To validate the connectivity between nodes in the Thread network using CLI.
Preparation in Advance
Hardware:
-
Two B91 Development Kits.
-
One Raspberry Pi 3B+ or greater with Raspbian OS Image.
-
A Linux machine with at least two USB ports.
-
An internet-connected switch (or Router) and several Ethernet cables.
Software:
-
Telink Burning and Debugging Tool 鈥斺€� LinuxBDT.
-
Serial port terminal tool, such as PuTTY.
-
Other tools such as, Git and West.
Prerequisites
Thread Concepts and OpenThread CLI
It might be helpful to go through the OpenThread Simulation codelab to get familiar with fundamental Thread concepts and the OpenThread CLI before this codelab.
Linux Machine
The Linux machine (Ubuntu v20.04 LTS or later) acts as the build machine to set up the Telink Zephyr development environment and flash all Thread development boards.
To accomplish these tasks, the Linux machine requires two available USB ports and internet connectivity.
Serial Port Connection and Terminals
You can directly plug the device into the USB port of Linux machine. Additionally, you will need a serial port terminal tool to access the devices.
In this codelab, terminal tool PuTTY is used for controlling the FTD Joiner and Raspberry Pi. It offers an overview of its usage, but other terminal software can also be employed.
Telink B91 Development Kit
This codelab needs two sets of B91 Development Kits.
The photo below displays the minimum required components in one set.
One of these kits will be used as RCP (Radio Co-Processor), while the other will function as FTD (Full Thread Device).
If you are not yet in possession of the kit, you can acquire more details from the Telink official website.
Some components to be used are as follows:
Table: Components required for B91 development kits
Index | Name |
---|---|
1 | Telink B91 Development Board |
2 | Telink Burning Board |
3 | 2.4Ghz Antenna |
4 | USB Cable (USB A to mini USB) |
Raspberry Pi 3B+ or greater with Raspbian OS Image
In this codelab, a Raspberry Pi 3B+ or greater with Raspbian Bullseye Lite OS image or Raspbian Bullseye with Desktop is needed.
It is connected to the internet via Ethernet and will be configured as the host for the OpenThread Border Router (OTBR).
Network Connection
An internet-connected switch (or router) and several Ethernet cables. They are used to connect the Raspberry Pi to the Linux machine, facilitating user configuration of the Raspberry Pi via the host.
LinuxBDT
Telink Burning and Debugging Tool (BDT), which applies to all Telink Chip series, allows you to erase and flash OpenThread firmware onto the Telink B91 Development Boards.
Install the X86-based linux version linuxBDT on your Linux machine.
Others
-
Git: for setting up Telink Zephyr Development Environment.
-
West: for manage Zephyr project and build OpenThread binaries.
Firmware Setting
Telink Zephyr Development Environment Setting
On the Linux machine, open an CLI terminal and start by executing the following commands to ensure that your APT is up-to-date.
$ sudo apt update
$ sudo apt upgrade
Once that is done, proceed with the following steps.
(1) Install the dependencies.
$ 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 currently requires minimum versions of main dependencies, such as CMake (3.20.0), Python3 (3.6), and Devicetree Compiler (1.4.6).
$ cmake --version
$ python3 --version
$ dtc --version
Verify the installed versions on your system before proceeding with the next steps.
If the versions are not correct, switch the APT mirror to a stable and up-to-date mirror, or manually update these dependencies.
(2) Install west.
$ pip3 install --user -U west
$ echo 'export PATH=~/.local/bin:"$PATH"' >> ~/.bashrc
$ source ~/.bashrc
Make sure that ~/.local/bin
is in your $PATH
environment variable.
(3) Get the Zephyr Project source code.
$ west init ~/zephyrproject
$ cd ~/zephyrproject
$ west update
$ west blobs fetch hal_telink
$ west zephyr-export
(4) Install additional Python dependencies for Zephyr.
$ pip3 install --user -r ~/zephyrproject/zephyr/scripts/requirements.txt
(5) Set up the Zephyr toolchain. Download the Zephyr toolchain (about 1~2 GB) to a local directory to allow you to flash most boards.
$ 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
Download the Zephyr SDK and place it in the recommended path, as shown below.
$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]
Where [-x.y.z] is optional text that can be any text, such as -0.16.1. The directory cannot be moved after the SDK is installed.
Then install the Zephyr toolchain.
$ 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) Build the Hello World example. First, verify that the official Zephyr project configuration is correct using the Hello World example, then proceed with setting up your custom project.
$ cd ~/zephyrproject/zephyr
$ west build -p auto -b tlsr9518adk80d samples/hello_world
Use the West build command to build the hello_world example from the root directory of the Zephyr repository.
You can find the firmware named zephyr.bin
under the build/zephyr directory
.
(7) Add the Zephyr environment script to ~/.bashrc
. Execute the following commands.
$ echo "source ~/zephyrproject/zephyr/zephyr-env.sh" >> ~/.bashrc
$ source ~/.bashrc
(8) Add the Telink Zephyr remote repository. Download the Telink repo locally as a development branch and update it.
$ cd ~/zephyrproject/zephyr
$ git remote add telink-semi https://github.com/telink-semi/zephyr
$ git fetch telink develop
$ git checkout develop
$ cd ..
$ west update
$ west blobs fetch hal_telink
For more information, you can refer to Zephyr Doc -- Getting Started Guide.
Telink LinuxBDT Setting
Download the Telink LinuxBDT tool and extract it to a local directory on your Linux machine, such as home directory ~
, enabling to flash firmware onto the B91 Development Board.
$ cd ~
$ wget http://wiki.telink-semi.cn/tools_and_sdk/Tools/BDT/LinuxBDT.tar.bz2
$ tar -vxf LinuxBDT.tar.bz2
Connect the Burning Board to the Linux machine via the USB interface, and then enter the following commands.
$ 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
If you see the message "Telink Web Debugger v3.6", it indicates that the BDT programmer has successfully connected to the Linux machine.
Firmware Compilation
This codelab will build two types of OpenThread firmware:
-
ot-cli-ftd
-
ot-rcp
The compilation methods are as follows锛�
(1) Radio Co-Processor (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) Full-Featured Thread Device with Interactive Command Line (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
Firmware Burning
Connect a B91 Development Board to the Burning Board using a USB cable as illustrated in the figure below.
In the command line, execute the following commands to perform firmware burning (using the flashing of the ot-cli-ftd
firmware as an example).
$ 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
The flash method for ot-rcp
is basically the same as that for ot-cli-ftd
. However, there are differences in the firmware paths and names.
After flashing, distinguish the two B91 Development Boards by marking them accordingly. Label the board flashed with ot-cli-ftd
as "FTD Joiner" and the board flashed with ot-rcp
as "RCP".
Configure a Serial Console for the FTD Joiner Device
As shown in the picture, directly plug the FTD Joiner into the USB port of the computer.
After connecting the FTD Joiner Device to the Linux machine, Open PuTTY.
Then create a new terminal, set the serial port information, and open the serial port.
The OpenThread command line reference is here: OpenThread CLI Reference.
Be sure to prefix all commands with ot
.
Examples:
> ot state
disabled
Done
> ot channel
11
Done
>
Set up the Raspberry Pi as a OpenThread Border Router
An OpenThread Border Router is a device consisting of two main parts锛�
-
Raspberry Pi contains all the services and firmware required to act as a Border Router (BR).
-
RCP is responsible for Thread communication.
Radio Co-Processor (RCP)
To flash the ot-rcp
firmware, follow the same steps as the ot-cli-ftd
firmware flashing process. Connect the B91 Development Board to a USB port on the Raspberry Pi, as depicted in the figure below.
Raspberry Pi
(1) Ensure that the Raspbian Bullseye Lite OS image or Raspbian Bullseye with Desktop is properly written to the SD card.
(2) You have the option to either SSH into the Raspberry Pi or work directly with the Raspbian Desktop. This codelab will use SSH.
(3) Before proceeding to install OTBR Docker in the next step, make sure to update the local repository and package manager first.
$ sudo apt-get update
$ sudp apt-get upgrade
Install Docker
If you just update the local repository and package manager APT at previous step, reboot Raspberry Pi and then open an SSH terminal window.
(1) Install Docker
$ curl -sSL https://get.docker.com | sh
(2) Put the current account into a Docker group to grant the permission so that sudo
does not need to be added in front of each command.
$ sudo usermod -aG docker $USER
You need to restart the Raspberry Pi to take effect.
(3) If Docker has not started, start it:
$ sudo dockerd
(4) The OTBR firewall scripts generate rules inside the Docker container. Prior to that, execute modprobe
to load the kernel module of iptables.
$ sudo modprobe ip6table_filter
Configure and Run Docker
This codelab directly pulls the OTBR Docker image from the OpenThread Docker Hub. This image has been tested and verified by the OpenThread team.
(1) Pull the latest image:
$ docker pull openthread/otbr:latest
(2) Check the image list in the Docker container:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
openthread/otbr latest db081f4de15f 6 days ago 766MB
(3) Determine the serial port name of the RCP device by checking /dev
, ttyACM0
indicates that the RCP is correctly connected.
$ ls /dev/tty*
...
/dev/ttyACM0
...
(4) Run OTBR Docker for the first time, and reference the serial port of RCP (ttyACM0
). If you want to continue using this OTBR Docker, use the command 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) Open a new SSH terminal window to test the connectivity between the Raspberry Pi and the RCP.
$ docker exec -ti otbr sh -c "sudo ot-ctl"
> state
disabled
Done
Optional docker commands:
Get information about the running Docker container:
$ docker ps -aq
Stop OTBR Docker:
$ docker stop otbr
Remove OTBR Docker:
$ docker rm otbr
Reload OTBR Docker:
$ docker restart otbr
At this point, a FTD Joiner device and an OTBR are ready, and you can proceed to the next step to build the Thread network.
Create a Thread Network
Create a Thread Network on RCP
We use the ot-ctl shell on the OTBR to establish a Thread network. If you exited the shell in last section, enter the following command to start it again in the SSH terminal:
$ docker exec -ti otbr sh -c "sudo ot-ctl"
Next, enter the commands in the order specified in the table, and ensure that each step achieves the expected result before proceeding to the next one.
Index | Command | Introduction | Expected Response |
---|---|---|---|
1 | dataset init new |
Create a new random network dataset. | Done |
2 | dataset commit active |
Commit new dataset to the Active Operational Dataset in non-volatile storage. | Done |
3 | ifconfig up |
Bring up the IPv6 interface. | Done |
4 | thread start |
Enable Thread protocol operation and attach to a Thread network. | Done |
Wait 10 seconds for the thread interface to be up. | |||
5 | state |
Check the device state.This command can be called multiple times until it becomes the leader and moves on to the next step. | leader Done |
6 | dataset active |
Check the complete Active Operational Dataset and record network key. | Active Timestamp: 1 Channel: 13 Channel Mask: 0x07fff800 Ext PAN ID: b07476e168eda4fc Mesh Local Prefix: fd8c:60bc:a98:c7ba::/64 Network Key: c312485187484ceb5992d2343baaf93d Network Name: OpenThread-599c PAN ID: 0x599c PSKc: 04f79ad752e8401a1933486c95299f60 Security Policy: 672 onrc 0 Done |
The network key randomly generated by OTBR during network creation will be used when ot-cli-ftd
devices join this Thread network.
Add the FTD Joiner to Thread through out-of-band commissioning
Out-of-band commissioning refers to the transmission of network credentials to devices waiting to join the network through non-wireless methods (for example, manually entering in the OpenThread CLI).
Enter the following commands in order in the serial console to the FTD Joiner.
Index | Command | Introduction | Expected Responses |
---|---|---|---|
1 | ot dataset networkkey c312485187484ceb5992d2343baaf93d |
Only the Network Key is necessary for a device to connect to a Thread network. | Done |
2 | ot dataset commit active |
Commit new dataset to the Active Operational Dataset in non-volatile storage. | Done |
3 | ot ifconfig up |
Bring up the IPv6 interface. | Done |
4 | ot thread start |
Enable Thread protocol operation and attach to a Thread network. | Done |
Wait 20 seconds while the device joins and configures itself. | |||
5 | ot state |
Check the device state. | child/router Done |
Note:
The FTD Joiner starts as a child and will turn into a router after a while, which is normal.
Topology
Enter commands such as ipaddr
, child table
, router table
in the SSH terminal to get responses like the following code snippets.
> 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
The RLOC16
of OTBR is 0xb000
and the RLOC16
of the FTD Joiner initially is 0xb001
.
Then the FTD Joiner's RLOC16
becomes 0x8400
after obtaining the Router ID.
It can be seen that the FTD Joiner has been upgraded from a child to a router.
Note:
- RLOC stands for Routing Locator, which identifies the device based on the position of the Thread device in the network topology.
- It is one of the several IPv6 addresses of the Thread device.
- For a detailed introduction, refer to IPv6 Addressing
The current Thread network contains two nodes, and the topology is as shown in the figure below.
Communication Between Thread Devices
ICMPv6 Communication
We use the ping
command to check whether Thread devices in the same network can communicate with each other.
First, use the ipaddr
command to get the RLOC of the device.
> 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
fd8c:60bc:a98:c7ba:5249:34ab:26d1:aff6
fe80:0:0:0:78e3:5410:9d61:1f7e
Done
Enter the following command in the serial console of the FTD Joiner to execute the ping operation.
> 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
The output response of the serial port indicates that the OTBR side has received the ping request, and the FTD Joiner has received the ping response returned by OTBR. The communication between the two devices is successful.
UDP Communication
The application services provided by OpenThread also include UDP. You can use the UDP API to pass information between nodes in the Thread network, or pass information to external networks through the Border Router.
The detailed introduction of OpenThread's UDP API is in the OpenThread CLI - UDP Example. This codelab will use some of the APIs in it to transmit information between OTBR and FTD Joiner.
First, get the Mesh-Local EID of OTBR. This address is also one of the IPv6 addresses of the Thread device, and it can be used to access Thread devices in the same Thread network partition.
> ipaddr mleid
fd8c:60bc:a98:c7ba:5249:34ab:26d1:aff6
Done
Enter the following commands in the SSH terminal to enable OTBR UDP and bind the device's 1022 port.
> udp open
Done
> udp bind :: 1022
Done
Enter the following commands in the serial console and enable the UDP of the FTD Joiner. Bind the device's 1022 port, and then send a 5-byte hello
message to OTBR.
> ot udp open
Done
> ot udp bind :: 1022
Done
> ot udp send fd8c:60bc:a98:c7ba:5249:34ab:26d1:aff6 1022 hello
Done
The SSH terminal outputs the following information. OTBR receives the hello
message from the FTD Joiner, which means the UDP communication is successful.
> 5 bytes from fd8c:60bc:a98:c7ba:9386:63cf:19d7:5a61 1022 hello
Congratulations
You've create a simple Thread network and verified the communication within this network.
You now know:
-
How to build and use the Telink Zephyr development environment.
-
How to build the
ot-cli-ftd
andot-rcp
binaries, as well as flash them onto Telink B91 Development Boards. -
How to set up a Raspberry Pi 3B+ or higher version as an OpenThread Border Router (OTBR) using Docker.
-
How to create a Thread network on OTBR.
-
How to add devices to the Thread network through out-of-band commissioning.
-
How to verify the connectivity between nodes in the Thread network.
Further Reading
Check out openthread.io and GitHub to learn about various OpenThread resources, including:
-
Supported Platforms - discover all the platforms that support OpenThread
-
Build OpenThread - further details on building and configuring OpenThread
-
Thread Primer - covers all the Thread concepts featured in this codelab
Reference documents:
License
Copyright (c) 2021-2023, The OpenThread Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
- Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.